diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 813aa07fd5..442e078699 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,7 +14,7 @@ // Use the `--dump-preprocessed-input` flag or the // `bindgen::Builder::dump_preprocessed_input` method to make your test case // standalone and without `#include`s, and then use C-Reduce to minimize it: -// https://github.com/rust-lang-nursery/rust-bindgen/blob/master/CONTRIBUTING.md#using-creduce-to-minimize-test-cases +// https://github.com/rust-lang/rust-bindgen/blob/master/CONTRIBUTING.md#using-creduce-to-minimize-test-cases ``` ### Bindgen Invocation diff --git a/.github/workflows/bindgen.yml b/.github/workflows/bindgen.yml new file mode 100644 index 0000000000..bd1489911e --- /dev/null +++ b/.github/workflows/bindgen.yml @@ -0,0 +1,209 @@ +name: bindgen + +on: + push: + branches: + - main + pull_request: + branches: + - main + merge_group: + branches: + - main + +jobs: + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install nightly + uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly + components: rustfmt + + - name: Run rustfmt + run: cargo +nightly fmt -- --check + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run clippy + run: cargo clippy --all-targets --workspace --exclude bindgen-integration --exclude tests_expectations -- -D warnings + + msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Read crate metadata + id: metadata + run: echo "rust-version=$(sed -ne 's/rust-version *= *\"\(.*\)\"/\1/p' Cargo.toml)" >> $GITHUB_OUTPUT + + - name: Install msrv for lib + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ steps.metadata.outputs.rust-version }} + + - name: Test lib with msrv + run: cargo +${{ steps.metadata.outputs.rust-version }} test --package bindgen + + - name: Install msrv for cli + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ steps.metadata.outputs.rust-version }} + + - name: Test cli with msrv + run: cargo +${{ steps.metadata.outputs.rust-version }} build --package bindgen-cli + + minimal: + runs-on: ubuntu-latest + env: + RUSTFLAGS: -D warnings + steps: + - uses: actions/checkout@v4 + + - name: Check without default features + run: cargo check -p bindgen --no-default-features --features=runtime + + docs: + runs-on: ubuntu-latest + env: + RUSTDOCFLAGS: -D warnings + steps: + - uses: actions/checkout@v4 + + - name: Generate documentation for `bindgen` + run: cargo doc --document-private-items --no-deps -p bindgen + + - name: Generate documentation for `bindgen-cli` + run: cargo doc --document-private-items --no-deps -p bindgen-cli + + quickchecking: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # TODO: Actually run quickchecks once `bindgen` is reliable enough. + - name: Build quickcheck tests + run: cd bindgen-tests/tests/quickchecking && cargo test + + test-expectations: + runs-on: ${{matrix.os}} + strategy: + matrix: + os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] + steps: + - uses: actions/checkout@v4 + + - name: Test expectations + run: cd bindgen-tests/tests/expectations && cargo test + + test: + runs-on: ${{matrix.platform.os}} + strategy: + matrix: + platform: + - os: ubuntu-latest + libtinfo: libtinfo5_6.3-2ubuntu0.1_amd64.deb + ubuntu_repo: https://mirrors.kernel.org/ubuntu/pool/universe/n/ncurses/ + - os: ubuntu-24.04-arm + libtinfo: libtinfo5_6.3-2ubuntu0.1_arm64.deb + ubuntu_repo: https://ports.ubuntu.com/ubuntu-ports/pool/universe/n/ncurses/ + llvm_version: ["9.0", "16.0"] + release_build: [0, 1] + no_default_features: [0, 1] + # FIXME: There are no pre-built static libclang libraries, so the + # `static` feature is not testable atm. + feature_runtime: [0, 1] + feature_extra_asserts: [0] + + include: + # Test with extra asserts + docs just with latest llvm versions to + # prevent explosion + - platform: + os: ubuntu-latest + libtinfo: libtinfo5_6.3-2ubuntu0.1_amd64.deb + ubuntu_repo: https://mirrors.kernel.org/ubuntu/pool/universe/n/ncurses/ + llvm_version: "16.0" + release_build: 0 + no_default_features: 0 + feature_extra_asserts: 1 + + # Ensure stuff works on macos too + - platform: + os: macos-latest + llvm_version: "16.0" + release_build: 0 + no_default_features: 0 + feature_extra_asserts: 0 + steps: + - uses: actions/checkout@v4 + + - name: Install stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + - name: Install libtinfo + if: startsWith(matrix.platform.os, 'ubuntu') + run: | + wget ${{matrix.platform.ubuntu_repo}}${{matrix.platform.libtinfo}} + sudo dpkg -i ${{matrix.platform.libtinfo}} + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v2.0.5 + with: + version: ${{matrix.llvm_version}} + - name: Run all the tests + env: + GITHUB_ACTIONS_OS: ${{matrix.platform.os}} + BINDGEN_RELEASE_BUILD: ${{matrix.release_build}} + BINDGEN_FEATURE_RUNTIME: ${{matrix.feature_runtime}} + BINDGEN_FEATURE_EXTRA_ASSERTS: ${{matrix.feature_extra_asserts}} + BINDGEN_NO_DEFAULT_FEATURES: ${{matrix.no_default_features}} + BINDGEN_RUST_FOR_LINUX_TEST: ${{startsWith(matrix.platform.os, 'ubuntu') && matrix.llvm_version == '16.0' && matrix.feature_extra_asserts == 0 && 1 || 0}} + run: ./ci/test.sh + + test-book: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # NOTE(emilio): Change deploy-book as well if you change this. + - name: Test book + run: | + curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar xz + ./mdbook build book + ./mdbook test book + + # FIXME(pvdrz): this should be done inside `bindgen-test` instead + test-no-headers: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Test `--help` + run: cargo run -- --help + + - name: Test `--version` + run: cargo run -- --version + + - name: Test `--generate-shell-completions` + run: cargo run -- --generate-shell-completions=bash + + # One job that "summarizes" the success state of this pipeline. This can then + # be added to branch protection, rather than having to add each job + # separately. + success: + runs-on: ubuntu-latest + needs: [rustfmt, clippy, msrv, minimal, docs, quickchecking, test-expectations, test, test-book, test-no-headers] + # GitHub branch protection is exceedingly silly and treats "jobs skipped + # because a dependency failed" as success. So we have to do some + # contortions to ensure the job fails if any of its dependencies fails. + if: always() # make sure this is never "skipped" + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: check if any dependency failed + run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml new file mode 100644 index 0000000000..56a264f7f7 --- /dev/null +++ b/.github/workflows/bump-version.yml @@ -0,0 +1,68 @@ +name: Bump version for release + +on: + workflow_dispatch: + inputs: + level: + description: | + Select the level of the release + required: true + type: choice + options: + - minor + - patch + +jobs: + bump-version: + permissions: + id-token: write + pull-requests: write + contents: write + + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Configure gitsign + uses: chainguard-dev/actions/setup-gitsign@main + + - name: Install cargo-release + uses: taiki-e/install-action@v1 + with: + tool: cargo-release + + - name: Install sd + uses: taiki-e/install-action@v1 + with: + tool: sd + + - name: Install npm + uses: actions/setup-node@v4 + + - name: Install doctoc + run: npm install doctoc + + - name: Bump version + run: | + cargo release version ${{ inputs.level }} --execute --no-confirm + + - name: Extract version + run: | + echo "version=$(cargo pkgid -p bindgen | cut -d '#' -f 2)" >> $GITHUB_ENV + + - name: Update changelog + run: | + sd "# Unreleased" "# Unreleased\n## Added\n## Changed\n## Removed\n## Fixed\n## Security\n\n# ${{ env.version }} ($(date -I))" CHANGELOG.md + ./node_modules/doctoc/doctoc.js CHANGELOG.md + + - name: Create PR + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: bump-version/${{ env.version }} + base: main + commit-message: "Bump crates version to ${{ env.version }}" + title: "Bump crates version to ${{ env.version }}" + body: | + This pull request was created automatically by GitHub Actions. diff --git a/.github/workflows/create-tag.yml b/.github/workflows/create-tag.yml new file mode 100644 index 0000000000..f636991c38 --- /dev/null +++ b/.github/workflows/create-tag.yml @@ -0,0 +1,49 @@ +name: Create tag for release + +on: + pull_request: + types: + - closed + workflow_dispatch: + inputs: + commit: + description: 'Commit hash' + required: true + type: string +jobs: + create-tag: + if: >- + (inputs.commit || false) || + (github.event.pull_request.merged == true && + github.event.pull_request.user.login == 'github-actions' && + github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name && + startsWith(github.event.pull_request.head.ref, 'bump-version') ) + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Compute the commit + run: | + if [[ -z "${{ inputs.commit }}" ]]; then + COMMIT=$(git rev-parse ${{ github.sha }}^@ | grep -Fvx ${{ github.event.pull_request.head.sha }}) + else + COMMIT="${{ inputs.commit }}" + fi + echo "commit=$COMMIT" >> $GITHUB_ENV + + - name: Install rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Extract version + run: | + echo "version=$(cargo pkgid -p bindgen | cut -d '#' -f 2)" >> $GITHUB_ENV + + - name: Create tag + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + commit_sha: ${{ env.commit }} + custom_tag: ${{ env.version }} diff --git a/.github/workflows/deploy-book.yml b/.github/workflows/deploy-book.yml new file mode 100644 index 0000000000..7b8cacc55d --- /dev/null +++ b/.github/workflows/deploy-book.yml @@ -0,0 +1,27 @@ +name: Deploy book + +on: + push: + branches: + - main + +jobs: + deploy-book: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Test book + run: | + curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.34/mdbook-v0.4.34-x86_64-unknown-linux-gnu.tar.gz | tar xz + ./mdbook build book + ./mdbook test book + + - name: Deploy book + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages + FOLDER: book/book diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..d8602f9ad9 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,27 @@ +# This is triggered after the Release workflow successfully completes its run +name: Publish on crates.io +on: + workflow_run: + workflows: + - Release + types: + - completed +env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} +jobs: + cargo-publish: + runs-on: ubuntu-latest + if: ${{ !github.event.pull_request && (github.event.workflow_run.conclusion == 'success') && (github.event.workflow.name == 'Release') }} + steps: + - name: Print workflow event name + run: echo "${{ github.event.workflow.name }}" + - name: Checkout sources + uses: actions/checkout@v4 + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + - name: Publish bindgen (lib) + run: cargo publish --package bindgen --token ${CARGO_REGISTRY_TOKEN} + - name: Publish bindgen-cli + run: cargo publish --package bindgen-cli --token ${CARGO_REGISTRY_TOKEN} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..6620b80c98 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,291 @@ +# This file was autogenerated by dist: https://opensource.axo.dev/cargo-dist/ +# +# Copyright 2022-2024, axodotdev +# SPDX-License-Identifier: MIT or Apache-2.0 +# +# CI that: +# +# * checks for a Git Tag that looks like a release +# * builds artifacts with dist (archives, installers, hashes) +# * uploads those artifacts to temporary workflow zip +# * on success, uploads the artifacts to a GitHub Release +# +# Note that the GitHub Release will be created with a generated +# title/body based on your changelogs. + +name: Release +permissions: + "contents": "write" + +# This task will run whenever you push a git tag that looks like a version +# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. +# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where +# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION +# must be a Cargo-style SemVer Version (must have at least major.minor.patch). +# +# If PACKAGE_NAME is specified, then the announcement will be for that +# package (erroring out if it doesn't have the given version or isn't dist-able). +# +# If PACKAGE_NAME isn't specified, then the announcement will be for all +# (dist-able) packages in the workspace with that version (this mode is +# intended for workspaces with only one dist-able package, or with all dist-able +# packages versioned/released in lockstep). +# +# If you push multiple tags at once, separate instances of this workflow will +# spin up, creating an independent announcement for each one. However, GitHub +# will hard limit this to 3 tags per commit, as it will assume more tags is a +# mistake. +# +# If there's a prerelease-style suffix to the version, then the release(s) +# will be marked as a prerelease. +on: + pull_request: + push: + tags: + - '**[0-9]+.[0-9]+.[0-9]+*' + +jobs: + # Run 'dist plan' (or host) to determine what tasks we need to do + plan: + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.plan.outputs.manifest }} + tag: ${{ !github.event.pull_request && github.ref_name || '' }} + tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} + publishing: ${{ !github.event.pull_request }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install dist + # we specify bash to get pipefail; it guards against the `curl` command + # failing. otherwise `sh` won't catch that `curl` returned non-0 + shell: bash + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.28.0/cargo-dist-installer.sh | sh" + - name: Cache dist + uses: actions/upload-artifact@v4 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/dist + # sure would be cool if github gave us proper conditionals... + # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible + # functionality based on whether this is a pull_request, and whether it's from a fork. + # (PRs run on the *source* but secrets are usually on the *target* -- that's *good* + # but also really annoying to build CI around when it needs secrets to work right.) + - id: plan + run: | + dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json + echo "dist ran successfully" + cat plan-dist-manifest.json + echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v4 + with: + name: artifacts-plan-dist-manifest + path: plan-dist-manifest.json + + # Build and packages all the platform-specific things + build-local-artifacts: + name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) + # Let the initial task tell us to not run (currently very blunt) + needs: + - plan + if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} + strategy: + fail-fast: false + # Target platforms/runners are computed by dist in create-release. + # Each member of the matrix has the following arguments: + # + # - runner: the github runner + # - dist-args: cli flags to pass to dist + # - install-dist: expression to run to install dist on the runner + # + # Typically there will be: + # - 1 "global" task that builds universal installers + # - N "local" tasks that build each platform's binaries and platform-specific installers + matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} + runs-on: ${{ matrix.runner }} + container: ${{ matrix.container && matrix.container.image || null }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json + steps: + - name: enable windows longpaths + run: | + git config --global core.longpaths true + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Rust non-interactively if not already installed + if: ${{ matrix.container }} + run: | + if ! command -v cargo > /dev/null 2>&1; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + fi + - name: Install dist + run: ${{ matrix.install_dist.run }} + # Get the dist-manifest + - name: Fetch local artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - name: Install dependencies + run: | + ${{ matrix.packages_install }} + - name: Build artifacts + run: | + # Actually do builds and make zips and whatnot + dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json + echo "dist ran successfully" + - id: cargo-dist + name: Post-build + # We force bash here just because github makes it really hard to get values up + # to "real" actions without writing to env-vars, and writing to env-vars has + # inconsistent syntax between shell and powershell. + shell: bash + run: | + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v4 + with: + name: artifacts-build-local-${{ join(matrix.targets, '_') }} + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + + # Build and package all the platform-agnostic(ish) things + build-global-artifacts: + needs: + - plan + - build-local-artifacts + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v4 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Get all the local artifacts for the global tasks to use (for e.g. checksums) + - name: Fetch local artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: cargo-dist + shell: bash + run: | + dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json + echo "dist ran successfully" + + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v4 + with: + name: artifacts-build-global + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + # Determines if we should publish/announce + host: + needs: + - plan + - build-local-artifacts + - build-global-artifacts + # Only run if we're "publishing", and only if local and global didn't fail (skipped is fine) + if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.host.outputs.manifest }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v4 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Fetch artifacts from scratch-storage + - name: Fetch artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: host + shell: bash + run: | + dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json + echo "artifacts uploaded and released successfully" + cat dist-manifest.json + echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v4 + with: + # Overwrite the previous copy + name: artifacts-dist-manifest + path: dist-manifest.json + # Create a GitHub Release while uploading all files to it + - name: "Download GitHub Artifacts" + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: artifacts + merge-multiple: true + - name: Cleanup + run: | + # Remove the granular manifests + rm -f artifacts/*-dist-manifest.json + - name: Create GitHub Release + env: + PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}" + ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}" + ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}" + RELEASE_COMMIT: "${{ github.sha }}" + run: | + # Write and read notes from a file to avoid quoting breaking things + echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt + + gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/* + + announce: + needs: + - plan + - host + # use "always() && ..." to allow us to wait for all publish jobs while + # still allowing individual publish jobs to skip themselves (for prereleases). + # "host" however must run to completion, no skipping allowed! + if: ${{ always() && needs.host.result == 'success' }} + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive diff --git a/.gitignore b/.gitignore index 9141908668..a610640e5e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,8 @@ target/ *~ bindgen-integration/Cargo.lock -tests/expectations/Cargo.lock +bindgen-tests/tests/expectations/Cargo.lock +bindgen-tests/tests/quickchecking/Cargo.lock #*# # Test script output @@ -16,4 +17,9 @@ __bindgen.* csmith-fuzzing/platform.info # Backups of test cases from C-Reduce -**.orig +**/*.orig + +# node.js files +node_modules +package-lock.json +package.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d8bc595d79..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,58 +0,0 @@ -language: rust - -os: - - linux - -rust: - - stable - -env: - global: - - CARGO_TARGET_DIR=/tmp/bindgen - matrix: - - LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions" - - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" BINDGEN_FEATURES="testing_only_extra_assertions" - - LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE= - - LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release" - - LLVM_VERSION="5.0" BINDGEN_JOB="misc" - - LLVM_VERSION="5.0" BINDGEN_JOB="quickchecking" - -matrix: - fast_finish: true - allow_failures: - - env: LLVM_VERSION=5.0 BINDGEN_JOB=rustfmt - -cache: - directories: - - $HOME/.cargo - - $HOME/.llvm-builds - -before_install: . ./ci/before_install.sh - -script: - - BINDGEN_JOB="$BINDGEN_JOB" BINDGEN_PROFILE="$BINDGEN_PROFILE" BINDGEN_FEATURES="$BINDGEN_FEATURES" ./ci/script.sh - -after_success: - - test "$TRAVIS_PULL_REQUEST" == "false" && - test "$TRAVIS_BRANCH" == "master" && - test "$BINDGEN_JOB" == "misc" && - ./ci/deploy-book.sh - -notifications: - webhooks: http://build.servo.org:54856/travis diff --git a/CHANGELOG.md b/CHANGELOG.md index 637b26f44a..74ff973751 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,123 +1,1418 @@ - - [Unreleased](#unreleased) - [Added](#added) - [Changed](#changed) - - [Deprecated](#deprecated) - [Removed](#removed) - [Fixed](#fixed) - [Security](#security) -- [0.33.1](#0331) - - [Fixed](#fixed-1) -- [0.33.0](#0330) +- [0.72.0 (2025-06-08)](#0720-2025-06-08) - [Added](#added-1) - [Changed](#changed-1) - - [Deprecated](#deprecated-1) - [Removed](#removed-1) + - [Fixed](#fixed-1) +- [v0.71.1 (2024-12-09)](#v0711-2024-12-09) - [Fixed](#fixed-2) - - [Security](#security-1) -- [0.32.2](#0322) - - [Fixed](#fixed-3) -- [0.32.1](#0321) - - [Fixed](#fixed-4) -- [0.32.0](#0320) +- [0.71.0 (2024-12-06)](#0710-2024-12-06) - [Added](#added-2) - [Changed](#changed-2) - - [Fixed](#fixed-5) -- [0.31.0](#0310) + - [Removed](#removed-2) + - [Fixed](#fixed-3) +- [0.70.1 (2024-08-20)](#0701-2024-08-20) - [Added](#added-3) - [Changed](#changed-3) - - [Deprecated](#deprecated-2) - - [Removed](#removed-2) - - [Fixed](#fixed-6) -- [0.30.0](#0300) + - [Removed](#removed-3) + - [Fixed](#fixed-4) + - [Security](#security-1) +- [0.70.0 (2024-08-16)](#0700-2024-08-16) - [Added](#added-4) - [Changed](#changed-4) - - [Deprecated](#deprecated-3) - - [Fixed](#fixed-7) -- [0.29.0](#0290) + - [Removed](#removed-4) + - [Fixed](#fixed-5) + - [Security](#security-2) +- [0.69.4 (2024-02-04)](#0694-2024-02-04) - [Added](#added-5) - [Changed](#changed-5) + - [Removed](#removed-5) + - [Fixed](#fixed-6) + - [Security](#security-3) +- [0.69.3 (2024-02-04)](#0693-2024-02-04) + - [Added](#added-6) + - [Changed](#changed-6) + - [Removed](#removed-6) + - [Fixed](#fixed-7) + - [Security](#security-4) +- [0.69.2 (2024-01-13)](#0692-2024-01-13) + - [Added](#added-7) + - [Changed](#changed-7) + - [Removed](#removed-7) - [Fixed](#fixed-8) + - [Security](#security-5) +- [0.69.1 (2023-11-02)](#0691-2023-11-02) + - [Fixed](#fixed-9) +- [0.69.0 (2023-11-01)](#0690-2023-11-01) + - [Added](#added-8) + - [Changed](#changed-8) + - [Removed](#removed-8) + - [Fixed](#fixed-10) + - [Security](#security-6) +- [0.68.1](#0681) + - [Fixed](#fixed-11) +- [0.68.0](#0680) + - [Added](#added-9) + - [Changed](#changed-9) + - [Removed](#removed-9) + - [Fixed](#fixed-12) +- [0.67.0](#0670) +- [0.66.1](#0661) + - [Removed](#removed-10) +- [0.66.0](#0660) + - [Added](#added-10) + - [Changed](#changed-10) + - [Removed](#removed-11) +- [0.65.1](#0651) + - [Fixed](#fixed-13) +- [0.65.0](#0650) + - [Added](#added-11) + - [Changed](#changed-11) + - [Removed](#removed-12) +- [0.64.0](#0640) + - [Added](#added-12) + - [Changed](#changed-12) +- [0.63.0](#0630) + - [Added](#added-13) + - [Changed](#changed-13) + - [Removed](#removed-13) +- [0.62.0](#0620) + - [Added](#added-14) + - [Changed](#changed-14) + - [Fixed](#fixed-14) +- [0.61.0](#0610) + - [Added](#added-15) + - [Changed](#changed-15) + - [Fixed](#fixed-15) +- [0.60.1](#0601) + - [Fixed](#fixed-16) +- [0.60.0](#0600) + - [Added](#added-16) + - [Fixed](#fixed-17) + - [Changed](#changed-16) + - [Removed](#removed-14) +- [0.59.2](#0592) +- [0.59.1](#0591) + - [Fixed](#fixed-18) +- [0.59.0](#0590) + - [Added](#added-17) + - [Fixed](#fixed-19) + - [Changed](#changed-17) +- [0.58.1](#0581) + - [Added](#added-18) +- [0.58.0](#0580) + - [Added](#added-19) + - [Fixed](#fixed-20) + - [Changed](#changed-18) + - [Deprecated](#deprecated) + - [Removed](#removed-15) + - [Fixed](#fixed-21) + - [Security](#security-7) +- [0.57.0](#0570) + - [Added](#added-20) + - [Fixed](#fixed-22) +- [0.56.0](#0560) + - [Added](#added-21) + - [Changed](#changed-19) + - [Fixed](#fixed-23) +- [0.55.1](#0551) + - [Fixed](#fixed-24) +- [0.55.0](#0550) + - [Removed](#removed-16) + - [Added](#added-22) + - [Changed](#changed-20) + - [Fixed](#fixed-25) +- [0.54.1](#0541) + - [Added](#added-23) + - [Changed](#changed-21) + - [Fixed](#fixed-26) +- [0.54.0](#0540) + - [Added](#added-24) + - [Changed](#changed-22) + - [Fixed](#fixed-27) +- [0.53.3](#0533) + - [Added](#added-25) + - [Fixed](#fixed-28) +- [0.53.2](#0532) + - [Changed](#changed-23) +- [0.53.1](#0531) + - [Added](#added-26) +- [0.53.0](#0530) + - [Added](#added-27) + - [Changed](#changed-24) + - [Fixed](#fixed-29) +- [0.52.0](#0520) + - [Added](#added-28) + - [Changed](#changed-25) + - [Fixed](#fixed-30) +- [0.51.1](#0511) + - [Fixed](#fixed-31) + - [Changed](#changed-26) +- [0.51.0](#0510) + - [Fixed](#fixed-32) + - [Changed](#changed-27) + - [Added](#added-29) +- [0.50.0](#0500) + - [Added](#added-30) +- [0.49.3](#0493) + - [Added](#added-31) +- [0.49.2](#0492) + - [Changed](#changed-28) +- [0.49.1](#0491) + - [Fixed](#fixed-33) + - [Changed](#changed-29) +- [0.49.0](#0490) + - [Added](#added-32) + - [Fixed](#fixed-34) + - [Changed](#changed-30) +- [0.48.1](#0481) + - [Fixed](#fixed-35) +- [0.48.0](#0480) + - [Changed](#changed-31) + - [Fixed](#fixed-36) +- [0.47.4](#0474) + - [Added](#added-33) +- [0.47.3](#0473) + - [Changed](#changed-32) +- [0.47.2](#0472) + - [Fixed](#fixed-37) +- [0.47.1](#0471) + - [Changed](#changed-33) + - [Fixed](#fixed-38) +- [0.47.0](#0470) + - [Changed](#changed-34) + - [Fixed](#fixed-39) +- [0.33.1 .. 0.46.0](#0331--0460) + - [Added](#added-34) + - [Removed](#removed-17) + - [Changed](#changed-35) + - [Fixed](#fixed-40) +- [0.33.1](#0331) + - [Fixed](#fixed-41) +- [0.33.0](#0330) +- [0.32.2](#0322) + - [Fixed](#fixed-42) +- [0.32.1](#0321) + - [Fixed](#fixed-43) +- [0.32.0](#0320) + - [Added](#added-35) + - [Changed](#changed-36) + - [Fixed](#fixed-44) +- [0.31.0](#0310) + - [Added](#added-36) + - [Changed](#changed-37) + - [Deprecated](#deprecated-1) + - [Removed](#removed-18) + - [Fixed](#fixed-45) +- [0.30.0](#0300) + - [Added](#added-37) + - [Changed](#changed-38) + - [Deprecated](#deprecated-2) + - [Fixed](#fixed-46) +- [0.29.0](#0290) + - [Added](#added-38) + - [Changed](#changed-39) + - [Fixed](#fixed-47) -------------------------------------------------------------------------------- - # Unreleased +## Added +## Changed +## Removed +- Removed support for generating code for rustc versions < 1.51. +## Fixed +- Typo in code for `--rustified-non-exhaustive-enums` (#3266) +## Security -Released YYYY/MM/DD +# 0.72.0 (2025-06-08) ## Added -* TODO (or remove section if none) + * Report enums in ParseCallbacks. + * Refactor item_name method to use ItemInfo struct. + * Add callback to modify contents of macro + * Discovery callbacks for functions and methods. + * Options to generate uncallable C++ functions. + * Provide option to get real virtual fn receiver. ## Changed -* TODO (or remove section if none) + * Generate bindings compatible with current rustc version by default. -## Deprecated +## Removed + + * Remove unused which-rustfmt feature + * Remove warning for opaque forward declarations -* TODO (or remove section if none) +## Fixed + + * More sophisticated handling of the triple in rust_to_clang_target + * Rename *-apple-ios-sim to ...simulator + * Fix OpenCL vectors that use "ext_vector_type". + * Fix union layout when it contains 0 sized array. + * Avoid crashing on variadic unions without layout information. + * Distinguish char16_t. + * Fix bugs in --clang-macro-fallback + * Add missed unsafe in the raw_set_bit function + * Use link_name for dynamic library loading + * Add "gen" to list of rust keywords in 'rust_mangle' + * Use appropriate `rustfmt --format ...` param + +# v0.71.1 (2024-12-09) +## Fixed +- Fix `--version` and `--generate-shell-completions` (#3040) + +# 0.71.0 (2024-12-06) +## Added +- Add the `ParseCallbacks::new_item_found` callback to expose the original and final name of structs, unions and enums (#2658). +- Add the `field_type_name` field to `FieldInfo` to expose the name of the type of a field (#2863) +- Add support for custom attributes with the `--with-attribute-custom` flag (#2866) +- Allow setting `--rust-target` to any Rust version supported by bindgen (#2993) +- Use c-string literals if the `--generate-cstr` flag is used for Rust targets after 1.77 under the 2021 edition (#2996) +- Add the `--rust-edition` flag which allows to select which Rust edition to target. (#3002, #3013) +- Use `unsafe extern` instead of `extern` in blocks for any Rust target after 1.82. (#3015) +## Changed +- The `--wrap-static-fns` related options no longer require the experimental feature or flag (#2928) +- Use the `Display` implementation instead of the `Debug` one for `BindgenError` in `bindgen-cli` (#3005) +## Removed +- Dropped support for any Clang versions strictly lower than 9.0 (#2932) +- Dropped support for any Rust version strictly lower than 1.33 (#2993) +## Fixed +- Represent opaque types in a FFI-safe way (#2880) +- Use the underlying type of any atomic type instead of panicking (#2920) +- Use the right characters for newlines on windows (#2923) +- Inlined namespaces are properly recognized now (#2950) +- Unsafe calls to `libloading` are now wrapped in `unsafe` blocks when using dynamic loading (#2961) +- The `ParseCallbacks::field_visibility` callback is now called for newtypes as well (#2967) +- Gate the use of the `addr_of` and `addr_of_mut` macros under the 1.51 rust version (#2988) + +# 0.70.1 (2024-08-20) +## Added +## Changed +## Removed +## Fixed +- Fix regression where the `const` layout tests were triggering the `unnecessary_operation` and `identity_op` clippy warnings. +## Security + +# 0.70.0 (2024-08-16) +## Added +- Add target mappings for riscv64imac and riscv32imafc. +- Add a complex macro fallback API (#2779). +- Add option to use DST structs for flexible arrays (--flexarray-dst, #2772). +- Add option to dynamically load variables (#2812). +- Add option in CLI to use rustified non-exhaustive enums (--rustified-non-exhaustive-enum, #2847). +- Add field_type_name to FieldInfo. +## Changed +- Remove which and lazy-static dependencies (#2809, #2817). +- Generate compile-time layout tests (#2787). +- Print `bindgen-cli` errors to stderr instead of stdout (#2840) +## Removed +## Fixed +- Fix `--formatter=prettyplease` not working in `bindgen-cli` by adding `prettyplease` feature and + enabling it by default for `bindgen-cli` (#2789) . +- Fix `--allowlist-item` so anonymous enums are no longer ignored (#2827). +- Use clang_getFileLocation instead of clang_getSpellingLocation to fix clang-trunk (#2824). +- Fix generated constants: `f64::INFINITY`, `f64::NEG_ INFINITY`, `f64::NAN` (#2854). +## Security +- Update `tempfile` and `rustix` due to [GHSA-c827-hfw6-qwvm](https://github.com/advisories/GHSA-c827-hfw6-qwvm). +# 0.69.4 (2024-02-04) +## Added +## Changed +- Allow older itertools. (#2745) ## Removed +## Fixed +## Security + +# 0.69.3 (2024-02-04) +## Added + +- Added blocklist_var (#2731) +- Stabilized thiscall_abi (#2661) + +## Changed -* TODO (or remove section if none) +- Use CR consistently on windows (#2698) +- Replaced peeking_take_while by itertools (#2724) +## Removed ## Fixed -* TODO (or remove section if none) +- Try to avoid repr(packed) for explicitly aligned types when not needed (#2734) +- Improved destructor handling on Windows (#2663) +- Support Float16 (#2667) +- Fix alignment contribution from bitfields (#2680) +- Fixed msrv build. ## Security -* TODO (or remove section if none) +- Updated shlex dependency (RUSTSEC-2024-0006) --------------------------------------------------------------------------------- +# 0.69.2 (2024-01-13) +## Added +## Changed +## Removed +## Fixed +- Fixed generation of extern "C" blocks with llvm 18+. See #2689. +## Security -# 0.33.1 +# 0.69.1 (2023-11-02) -Released 2018/02/14 +## Fixed +- Allow to run `bindgen -v` without an input header argument. +# 0.69.0 (2023-11-01) + +## Added +- Added the `ParseCallbacks::header_file` callback which runs on every filename passed to `Builder::header`. +- Added the `CargoCallbacks::new` constructor which emits a cargo-rerun line + for every input header file by default. +- Added the `CargoCallbacks::rerun_on_header_files` method to configure whether + a cargo-rerun line should be emitted for every input header file. +## Changed +- The `--wrap-static-fns` feature was updated so function types that has no + argument use `void` as its sole argument. +- `CargoCallbacks` is no longer a [unit-like + struct](https://doc.rust-lang.org/reference/items/structs.html) and the + `CargoCallbacks` constant was added to mitigate the breaking nature of this + change. This constant has been marked as deprecated and users will have to + use the new `CargoCallbacks::new` method in the future. +## Removed ## Fixed +- Allow compiling `bindgen-cli` with a static libclang. +- Emit an opaque integer type for pointer types that don't have the same size + as the target's pointer size. +- Avoid escaping Objective-C method names unless they are `Self`, `self`, + `crate` or `super`. +## Security -* Reverted the dependency update to `quote = "0.4"` and addition of the - `proc_macro2` dependency. The `proc_macro2` crate depends on `rustc` internal - libraries, which means that CLIs which use it must be run under `rustup`, - which is not acceptable for `bindgen`. [#1248][] +# 0.68.1 + +## Fixed +- Fixed errors on the windows artifact build process. -[#1248]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1248 +# 0.68.0 --------------------------------------------------------------------------------- +## Added +- The `system` ABI is now supported as an option for the `--override-abi` flag. +- The `allowlist_item` method and the `--allowlist-item` flag have been + included to filter items regardless or their kind. +- Include installers as release artifacts on Github. +## Changed +- The `Clone` implementation for `_BindgenUnionField` has been changed to pass + the `incorrect_clone_impl_on_copy_type` Clippy lint. +- The `c_unwind` ABI can be used without a feature gate for any Rust target version + equal to or greater than 1.71. + This comes as a result of the ABI being stabilised (in Rust 1.71). +- Formatting changes when using prettyplease as a formatter due to a new + prettyplease version. +- Avoid generating invalid `CStr` constants when using the `--generate-cstr` + option. +## Removed +- The `extra_assert` and `extra_assert_eq` macros are no longer exported. +## Fixed +- Bindgen no longer panics when parsing an objective-C header that includes a + Rust keyword that cannot be a raw identifier, such as: `self`, `crate`, + `super` or `Self`. -# 0.33.0 +# 0.67.0 + +This version was skipped due to some problems on the release workflow. -Released YYYY/MM/DD +# 0.66.1 + +## Removed +* Revert source order sorting (#2543) due to correctness regressions #2558. + +# 0.66.0 ## Added -* TODO (or remove section if none) +* Added the `--generate-cstr` CLI flag to generate string constants as `&CStr` + instead of `&[u8]`. (Requires Rust 1.59 or higher.) +* Added the `--generate-shell-completions` CLI flag to generate completions for + different shells. +* The `--wrap-static-fns` option can now wrap `va_list` functions as variadic functions + with the experimental `ParseCallbacks::wrap_as_variadic_fn` method. +* Add target mappings for riscv32imc and riscv32imac. +* Add the `ParseCallbacks::field_visibility` method to modify field visibility. ## Changed -* TODO (or remove section if none) +* Non-UTF-8 string constants are now generated as references (`&[u8; SIZE]`) + instead of arrays (`[u8; SIZE]`) to match UTF-8 strings. +* Wrappers for static functions that return `void` no longer contain a `return` + statement and only call the static function instead. +* The `--wrap-static-fns` option no longer emits wrappers for static variadic + functions. +* Depfiles generated with `--depfile` or `Builder::depfile` will now properly + generate module names and paths that include spaces by escaping them. To make + the escaping clear and consistent, backslashes are also escaped. +* Updated `bitflags` dependency to 2.2.1. This changes the API of `CodegenConfig`. +* Prettyplease formatting is gated by an optional, enabled by default Cargo + feature when depending on `bindgen` as a library. +* Items are now parsed in the order they appear in source files. This may result in + auto-generated `_bindgen_*` names having a different index. +* Use default visibility for padding fields: Previously, padding fields were + always public. Now, they follow the default visibility for the type they are + in. +* Compute visibility of bitfield unit based on actual field visibility: A + bitfield unit field and its related functions now have their visibility + determined based on the most private between the default visibility and the + actual visibility of the bitfields within the unit. -## Deprecated +## Removed +* Remove redundant Cargo features, which were all implicit: + - bindgen-cli: `env_logger` and `log` removed in favor of `logging` + - bindgen (lib): + + `log` removed in favor of `logging` + + `which` removed in favor of `which-logging` + + `annotate-snippets` removed in favor of `experimental` + +* Prettyplease is available as a `Formatter` variant now. + +# 0.65.1 + +## Fixed + +* The `Builder::rustfmt_bindings` method was added back and tagged as + deprecated instead of being removed. +* Broken documentation links were fixed. + +# 0.65.0 + +## Added + * Added the `Builder::default_visibility` method and the + `--default-visibility` flag to set the default visibility of fields. (#2338) + * Added the `--formatter` CLI flag with the values `none`, `rustfmt` and + `prettyplease` to select which tool will be used to format the bindings. The + default value is `rustfmt`. (#2453) + * Added the `Builder::formatter` method and the `Formatter` type to select + which tool will be used to format the bindings. (#2453) + * Added the `Builder::emit_diagnostics` method and the `--emit-diagnostics` + flag to enable emission of diagnostic messages under the `experimental` + feature. (#2436) + * Added support for the `"efiapi"` calling convention (#2490). + * Added the `ParseCallbacks::read_env_var` method which runs everytime + `bindgen` reads and environment variable. (#2400) + * Added the `ParseCallbacks::generated_link_name_override` method which allow + overriding the link name of items. (#2425) + * Add support for C `enum`s when generating code while using the + `--wrap-static-fns` feature. (#2415) + +## Changed + * Static functions with no arguments use `void` as their single argument + instead of having no arguments when the `--wrap-static-fns` flag is used. + (#2443) + * The source file generated when the `--wrap-static-fns` flag is enabled now + contains `#include` directives with all the input headers and all the source + code added with the `header_contents` method. (#2447) + * The source file generated when the `--wrap-static-fns` flag no longer uses + `asm` labeling and the link name of static wrapper functions is allowed to + be mangled. (#2448) + * The documentation of the generated `type` aliases now matches the comments + of their `typedef` counterparts instead of using the comments of the aliased + types. (#2463) + * The `Builder::rustfmt_bindings` methods and the `--no-rustfmt-bindings` flag + are now deprecated in favor of the formatter API. (#2453) + +## Removed + * The following deprecated flags were removed: `--use-msvc-mangling`, + `--rustfmt-bindings` and `--size_t-is-usize`. (#2408) + * The `Bindings::emit_warnings` and `Bindings::warnings` methods were removed + in favor of `--emit-diagnostics`. (#2436) + * Bindgen no longer generates C string constants that cannot be represented as + byte slices. (#2487) + +# 0.64.0 + +## Added + * Added a new set of flags `--with-derive-custom`, + `--with-derive-custom-struct`, `--with-derive-custom-enum` and + `--with-derive-custom-enum` to add custom derives from the CLI. + * Added the `--experimental` flag on `bindgen-cli` and the `experimental` + feature on `bindgen` to gate experimental features whose implementation is + incomplete or are prone to change in a non-backwards compatible manner. + * Added a new set of flags and their equivalent builder methods + `--wrap-static-fns`, `--wrap-static-fns-suffix` and `--wrap-static-fns-path` + to generate C function wrappers for `static` or `static inline` functions. + This feature is experimental. + +## Changed + * Fixed name collisions when having a C `enum` and a `typedef` with the same + name. + * The `ParseCallbacks::generated_name_override` method now receives `ItemInfo<'_>` as + argument instead of a `&str`. + * Updated the `clang-sys` crate version to 1.4.0 to support clang 15. + * The return type is now omitted in signatures of functions returning `void`. + * Updated the `clap` dependency for `bindgen-cli` to 4. + * Rewrote the `bindgen-cli` argument parser which could introduce unexpected + behavior changes. + * The `ParseCallbacks::add_derives` method now receives `DeriveInfo<'_>` as + argument instead of a `&str`. This type also includes the kind of target type. + +# 0.63.0 + +## Added + * new feature: `process_comments` method to the `ParseCallbacks` trait to + handle source code comments. -* TODO (or remove section if none) +## Changed + * Only wrap unsafe operations in unsafe blocks if the `--wrap_unsafe_ops` + option is enabled. + * Replace the `name: &str` argument for `ParseCallbacks::add_derives` by + `info: DeriveInfo`. + * All the rust targets equal or lower than `1.30` are being deprecated and + will be removed in the future. If you have a good reason to use any of these + targets, please report it in the issue tracker. + +## Removed + + * The following deprecated methods and their equivalent CLI arguments were + removed: `whitelist_recursively`, `hide_type`, `blacklist_type`, + `blacklist_function`, `blacklist_item`, `whitelisted_type`, + `whitelist_type`, `whitelist_function`, `whitelisted_function`, + `whitelist_var`, `whitelisted_var`, `unstable_rust`. + +# 0.62.0 + +## Added + + * new feature: `--override-abi` flag to override the ABI used by functions + matching a regular expression. + * new feature: allow using the `C-unwind` ABI in `--override-abi` on nightly + rust. + +## Changed + + * Regex inputs are sanitized so alternation (`a|b`) is handled correctly but + wildcard patterns (`*`) are now considered invalid. The `.*` pattern can be + used as a replacement. + * the `ParseCallbacks`trait does not require to implement `UnwindSafe`. + * the `Builder::parse_callbacks` method no longer overwrites previously added + callbacks and composes them in a last-to-first manner. + * any generated rust code containing unsafe operations inside unsafe functions + is wrapped in unsafe blocks now. + +## Fixed + + * Various issues with upcoming clang/libclang versions have been fixed. + +# 0.61.0 + +Released 2022/10/16 + +## Added + + * new feature: `--sort-semantically` flag to sort the output in a predefined + manner [(#1743)]. + * new feature: `Bindgen::emit_warnings` method to emit warnings to stderr in + build scripts. + * new feature: `--newtype-global-enum` flag to generate enum variants as + global constants. + * new feature: `--default-non-copy-union-style` flag to set the default style + of code used to generate unions with non-`Copy` members. + * new feature: `--bindgen-wrapper-union` flag to mark any union that matches a + regex and has a non-Copy member to use a bindgen-generated wrapper for its + fields. + * new feature: `--manually-drop-union` flag to mark any union that matches a + regex and has a non-`Copy` member to use `ManuallyDrop`. + * new feature: `--merge-extern-blocks` flag to merge several `extern` blocks + that have the same ABI. + * new feature: `--no-size_t-is-usize` flag to not bind `size_t` as `usize`. + * new feature: `Builder` implements `Clone`. + +## Changed + + * clap and regex have been updated, new msrv is 1.57. + * The `--enable-function-attribute-detection` flag is also used to detect + diverging functions so the generated bindings use `!` as the return type. + * The `--size_t-is-usize` flag is enabled by default. + * Unused type aliases for `` types are no longer emitted. + * The `blocklist` options now can be used to block objective-C methods. + * The `core::ffi` module is used the sized raw integer types + instead of `std::os::raw` if the Rust target version is `1.64` or higher and + the `--use-core` flag is enabled. + * The `bindgen` CLI utility must be installed using `cargo install + bindgen-cli` now. + * Using `bindgen` as a library no longer pulls clap and any other CLI + related dependencies. + +## Fixed + + * Const correctness of incomplete arrays has been fixed. (#2301) + * C++ inline namespaces don't panic. (#2294) + +[(#1743)]: https://github.com/rust-lang/rust-bindgen/issues/1743 + +# 0.60.1 + +Released 2022/06/06 + +## Fixed + + * Fixed stack overflow in generated tests for structs with many fields (#2219). + +# 0.60.0 + +Released 2022/06/05 + +## Added + + * Objective-C structs now derive `Debug` and `Copy` to support C and Objective-C structs. [(#2176)][] + * Allow fully-qualified derives. (#2156) + * Bindings generation now returns a more suitable error (#2125) + * `--version --verbose` now prints clang version (#2140). + * Experimental vtable generation (#2145). + * Added an `--allowlist-file` option (#2122). + * Support for vectorcall ABI (#2177). + +## Fixed + + * Fixed lifetimes with Objective-C trait templates. [(#2176)][] + * Fixed objc imports for non-`#[macro_use]` use. [(#2176)][] + * Handle differences between clang and rustc targets for RISCV (#2137). + * `BINDGEN_EXTRA_CLANG_ARGS` is respected on the CLI now (#1723). + * Use common type alias for anonymous enums in consts mode (#2191) + * Look for `#[must_use]` in typedefs (#2206). + * Fixed derive on packed structs (#2083). + * Fixed warnings on layout tests (#2203). + +## Changed + + * cexpr, clap, and nom have been updated, new msrv is 1.54. ## Removed -* TODO (or remove section if none) + * Support for ancient libclang versions has been removed. + + [(#2176)]: https://github.com/rust-lang/rust-bindgen/pull/2176 + +# 0.59.2 + +Released 2021/11/26 + + * cexpr+env_logger bump. + * Various fixes for C++ crashes / hangs. + * Enums now respect annotations and derives properly in more cases. + * Some more APIs (blocklist-file, etc). + * 'static lifetime is elided when appropriate. + +# 0.59.1 + +Released 2021/07/26 + +## Fixed + + * Fixed incorrect bitfield constructors generated for very large bitfields (#2082). + +# 0.59.0 + +Released 2021/07/20 + +## Added + + * Support emitting Makefile-syntax depfiles (#2026) + * Add a C naming option (#2045) + * Allow explicit padding (#2060) + * Add custom derives callback (#2059) + * Let Rust derive everything but Default for large arrays in 1.47 and later (#2070). + +## Fixed + + * Constants now have docstrings (#2027) + * Don't generate bindings for deleted member functions. (#2044) + * Zero out padding in custom Default trait implementations (#2051) + * Identify forward declarations in params. (#2052) + * Add env var EXTRA_CLANG_ARGS_. (#2031) + +## Changed + + * cexpr and nom have been updated, new msrv is 1.44 (#2073). + +# 0.58.1 + +Released 2021/04/06 + +## Added + + * Re-introduced unintentionally removed + `bindgen::Builder::whitelist_recursively` (deprecated in favor of + `bindgen::Builder::allowlist_recursively`). [#2022][] + +# 0.58.0 + +Released 2021/04/03 + +## Added + + * Add option to translate enum integer types to native Rust integer types. + [#2004][] + * Add callback to check derives for blocklisted types. [#2007][] + * Add a flag to ensure all symbols are resolved when a library is loaded. + [#2013][] + * Add from_library for generated dynamic library structs [#2011][]. ## Fixed -* TODO (or remove section if none) + * Track union layout more accurately. Fixes [an AArch64 bug] and [makes the + bindings more portable] where unions could return garbage data ([#1984]) + * Use original name when checking allowlist for anonymous enum variants. [#2006][] + +## Changed + +## Deprecated + +* `bindgen::Builder::whitelist_type` is deprecated in favor of + `bindgen::Builder::allowlist_type`. [#1812][] + +* `bindgen::Builder::whitelist_function` is deprecated in favor of + `bindgen::Builder::allowlist_function`. [#1812][] + +* `bindgen::Builder::whitelist_var` is deprecated in favor of + `bindgen::Builder::allowlist_var`. [#1812][] + +* `--whitelist-type` is deprecated in favor of + `--allowlist-type`. [#1812][] + +* `--whitelist-function` is deprecated in favor of + `--allowlist-function`. [#1812][] + +* `--whitelist-var` is deprecated in favor of + `--allowlist-var`. [#1812][] + +* `bindgen::Builder::blacklist_type` is deprecated in favor of + `bindgen::Builder::blocklist_type`. [#1812][] + +* `bindgen::Builder::blacklist_function` is deprecated in favor of + `bindgen::Builder::blocklist_function`. [#1812][] + +* `bindgen::Builder::blacklist_item` is deprecated in favor of + `bindgen::Builder::blocklist_item`. [#1812][] + +* `--blacklist-type` is deprecated in favor of + `--blocklist-type`. [#1812][] + +* `--blacklist-function` is deprecated in favor of + `--blocklist-function`. [#1812][] + +* `--blacklist-item` is deprecated in favor of + `--blocklist-item`. [#1812][] + +[#1984]: https://github.com/rust-lang/rust-bindgen/pull/1984 +[an AArch64 bug]: https://github.com/rust-lang/rust-bindgen/issues/1973 +[makes the bindings more portable]: https://github.com/rust-lang/rust-bindgen/issues/1983 + +## Removed + +## Fixed ## Security -* TODO (or remove section if none) +--- + +# 0.57.0 + +Released 2021/02/01 + +## Added + +* Expose module-raw-lines to the CLI (#1936) +* Added an option to fit macro constants to smaller types (#1945) +* Add an option to respect C++ access specifiers on fields (#1968) + +## Fixed + +* Improved C++ auto-detection (#1933) +* Fixed layout of bitfields in some edge cases (#1950) +* Escape the dyn keyword properly (#1951) +* Use absolute paths for unsaved files passed to clang (#1857). + +# 0.56.0 + +Released 2020/11/26 + +## Added + +* Objective-c bindings generate `From for ParentClass` as well as `TryFrom for ChildClass` ([#1883][]). +* Experimental dynamic library support via `dynamic_library_name` (#1846). +* Option to disable deriving `Default` on a per-struct basis (#1930). + +## Changed + +* Objective-c bindings borrow self rather than take ownership ([#1883][]). +* Templates and enums now correctly use the same naming scheme as other types + (#1891). + +## Fixed + +* Constructors in wasm32 now return a value. (#1877). +* Fixed objective-c protocol impl blocks for parent classes's protocols ([#1883][]). + +[#1883]: https://github.com/rust-lang/rust-bindgen/issues/1883 + +-------------------------------------------------------------------------------- + +# 0.55.1 + +Released 2020/08/24. + +## Fixed + + * Fixed a regression where anonymous enums referenced by members or such won't + generate valid Rust code. (#1882). + +-------------------------------------------------------------------------------- + +# 0.55.0 + +Released 2020/08/23. + +## Removed + + * Support for libclang 3.8 has been removed (#1830). + +## Added + + * Added options to avoid deriving the Debug trait (#1858). + + * Added options to allow to override the default anonymous field prefix (#1859). + + * Added options to allow to override the default macro integer type from the + command line (#1863). + +## Changed + + * Typed anonymous enums now generate better code (#1850). + + * Objective-C bindings are more idiomatic now (#1847). + + * Updated to clang-sys 1.0. Minimum supported rust version is 1.40 as + a consequence of that change. + +## Fixed + + * Fixed constness of multi-dimensional arrays in some cases (#1861). + + * Fixed wrong target given to clang when compiling with a target which doesn't + match the target clang expects (#1870, #1878). + + * Fixed wrong flags being computed for cross-compilation cases where the target + wasn't explicitly provided via clang flags (#1872). + +Thanks again to all the awesome contributors that sent patches included in this +release! + +-------------------------------------------------------------------------------- + +# 0.54.1 + +Released 2020/07/06. + +**Yanked**: The change in #1798 is technically breaking, see PR for details. + +## Added + + * Added ParseCallbacks::func_macro to be able to process function-like macros. + (#1792). + + * Allowed IntKind::Custom to represent paths instead of idents (#1800). + +## Changed + + * Generated comment now includes the bindgen version, and can be disabled + (#1814). + + * Various documentation improvements. + +## Fixed + + * Typedefs for types with the same names as rust primitive types compiles + (#1798). + + * Bindgen dependencies will now get rebuilt when various environment variables + that affect bindgen change (#1809, #1813). + + * Various fixes to command_line_flags (#1816, #1819, #1821). + + * Functions that start with `operator` now get properly generated (#1817). + + +Thanks to all the awesome contributors that sent patches included in this +release! + +-------------------------------------------------------------------------------- + +# 0.54.0 + +Released 2020/05/21. + +## Added + + * New command line flag to allow disabling untagged unions (#1789). + +## Changed + + * Various documentation improvements (#1764, #1751, #1757). + * Better Objective-C support (#1722, #1750). + +## Fixed + + * Rust method wrappers are not emitted for blacklisted functions (#1775). + * Fixed function signatures in some edge cases involving Objective-C or + `__stdcall` (#1781). + +-------------------------------------------------------------------------------- + +# 0.53.3 + +Released 2020/05/21. + +*Note: This release contains the same fixes and additions as 0.54.0, but without +the Objective-C breaking changes* + +## Added + + * New command line flag to allow disabling untagged unions (#1789). + +## Fixed + + * Rust method wrappers are not emitted for blacklisted functions (#1775). + * Fixed function signatures in some edge cases involving Objective-C or + `__stdcall` (#1781). + +-------------------------------------------------------------------------------- + +# 0.53.2 + +Released 2020/03/10. + +## Changed + + * clang-sys and cexpr have been updated (#1741 and #1744). + * Runtime of some commands has been improved (#1737) + * Some error messages have been improved (#1734). + +-------------------------------------------------------------------------------- + +# 0.53.1 + +Released 2020/02/03. + +## Added + + * Opt-in to convert size_t to usize again (#1720). + +-------------------------------------------------------------------------------- + +# 0.53.0 + +Released 2020/02/02. + +## Added + + * Support for wasm_import_module. (#1691). + * non_exhaustive feature is now stable (#1698). + * Various objective-C improvements (#1702). + +## Changed + + * Removed size_t to usize conversion rule (#1688). + +## Fixed + + * Various unneeded padding fields shouldn't be generated anymore (#1710). + * Bitfields on packed structs should generate correct layout (#1717). + * Too large bitfield blocks now generate compiling code (#1719). + +-------------------------------------------------------------------------------- + +# 0.52.0 + +Released 2019/11/19. + +## Added + + * Added `newtype` enum style, much like `bitfield` but without the bitwise ops + (#1677). + * Added support for `MaybeUninit` rather than `mem::uninitialized()` (#1666). + * Allowed static linking (#1620) behind a feature. Note that **if you're using + `default-features = false`, you probably want to use the `"runtime"` feature + to get the same behavior as before**. + +## Changed + + * Use c_void from core when --use-core is specified and available (#1634). + * Various dependencies and features are non-default now (like `regex` unicode + features). + +## Fixed + + * Fixed crash when unknown keywords are used before a namespace (#1678). + * Do not generate implementation for clone for flexible array members (#1664). + * Fixed `#[must_use]` support for libclang 9+ (#1646). + * Fixed `BitfieldUnit` constructor to handle 64 bit wide bitfields on 32 bit (#1640). + * Added a `ParseCallbacks` handler for included files. (#1637). + +# 0.51.1 + +Released 2019/09/23. + +## Fixed + + * Mismatched `Ord` and `PartialOrd` implementations were fixed, which regresses + bindgen in funny ways when using rustc nightly. Dot releases for a few of the + previous versions of bindgen will be created with this fix. Also, + a `v0.51.1-oldsyn` version was uploaded without the syn update. [#1627][] + +## Changed + + * Syn and related dependencies have been updated. [#1611][] + + * Switches added to allow less dependencies. In + particular: It won't pull `failure` and related dependencies by default, and + there's a default-on `which-rustfmt` feature which allows to get rid of + `which` altogether. [#1615][] / [#1625][] + + * `fxhash` dependency was switched to `rustc-hash`. [#1626][] + +[#1627]: https://github.com/rust-lang/rust-bindgen/issues/1627 +[#1611]: https://github.com/rust-lang/rust-bindgen/issues/1611 +[#1615]: https://github.com/rust-lang/rust-bindgen/issues/1615 +[#1625]: https://github.com/rust-lang/rust-bindgen/issues/1625 +[#1626]: https://github.com/rust-lang/rust-bindgen/issues/1626 +[#1627]: https://github.com/rust-lang/rust-bindgen/issues/1627 + +# 0.51.0 + +Released 2019/07/26. + +## Fixed + + * Improve workaround for LLVM stack overflow when evaluating value-dependent + expressions. [#1591][] + + * Bindgen will properly detect the layout of incomplete arrays. [#1592][] + + * Bindgen will properly detect the layout of empty unions and forward + declarations of unions. [#1593][] and [#1595][]. Thanks @pmarks! + +## Changed + + * Refactored the way layout of `wchar_t` is computed. This is a breaking change + since `IntKind::WChar` (exposed in `ParseCallbacks`) no longer needs a `size` + member. [#1596][] + +## Added + + * Bindgen now reads `RUSTFMT` in the environment to try to find a suitable + `rustfmt` binary. [#1602][] + +[#1591]: https://github.com/rust-lang/rust-bindgen/issues/1591 +[#1592]: https://github.com/rust-lang/rust-bindgen/issues/1592 +[#1593]: https://github.com/rust-lang/rust-bindgen/issues/1593 +[#1595]: https://github.com/rust-lang/rust-bindgen/issues/1595 +[#1596]: https://github.com/rust-lang/rust-bindgen/issues/1596 +[#1602]: https://github.com/rust-lang/rust-bindgen/issues/1602 + +# 0.50.0 + +Released 2019/07/01. + +## Added + +* Fixed pointers to Objective C blocks [#1582][]. + +* Various bindgen auto-generated types are now constructible in `const fn` + contexts [#1571][] + +* It is possible to generate `#[non_exhaustive]` enums for rust nightly targets. + [#1575][] + +* It is possible to avoid building clap now if you're using bindgen as + a library. [#1581][]. + +[#1571]: https://github.com/rust-lang/rust-bindgen/issues/1571 +[#1575]: https://github.com/rust-lang/rust-bindgen/issues/1575 +[#1581]: https://github.com/rust-lang/rust-bindgen/issues/1581 +[#1582]: https://github.com/rust-lang/rust-bindgen/issues/1582 + +# 0.49.3 + +Released 2019/06/25. **YANKED** + +## Added + +* Various bindgen auto-generated types are now constructible in `const fn` + contexts [#1571][] + +* It is possible to generate `#[non_exhaustive]` enums for rust nightly targets. + [#1575][] + +* It is possible to avoid building clap now if you're using bindgen as + a library. [#1581][]. + +[#1571]: https://github.com/rust-lang/rust-bindgen/issues/1571 +[#1575]: https://github.com/rust-lang/rust-bindgen/issues/1575 +[#1581]: https://github.com/rust-lang/rust-bindgen/issues/1581 + +# 0.49.2 + +Released 2019/05/22 + +## Changed + +* Bindgen now has an option to generate array arguments as pointer to the array, + not to the element (so `void foo(int arr[2])` would be generated as + `arr: *mut [c_int; 2]` rather than `arr: *mut c_int`. Thanks @elichai! + [#1564][]. + +[#1564]: https://github.com/rust-lang/rust-bindgen/issues/1564 + +# 0.49.1 + +Released 2019/05/16 + +## Fixed + +* Bindgen will not emit `#[link_name]` attributes in win32 and macos for + C functions and constants where it can detect it's not needed (thanks + @michaelwoerister!). [#1558][] + +## Changed + +* Bindgen will no longer use `hashbrown` internally, and will use fxhash + and `std::HashMap`. This is equivalent for newer `rustc`s since `hashbrown` + was merged in libstd, and the performance difference should be close to zero + for older rustcs. + +[#1558]: https://github.com/rust-lang/rust-bindgen/issues/1558 + +# 0.49.0 + +Released 2019/03/27 + +## Added + +* BINDGEN_EXTRA_CLANG_ARGS environment variable was added (thanks @jhwgh1968!). [#1537][] + +## Fixed + +* Bindgen will properly name parameters inside nested function pointer + declarations (thanks @flowbish!). [#1535][] + +## Changed + +* Derive code was greatly improved by @jethrogb. [#1540][] +* Derive analysis now handles trivial types more gracefully. [#1492][] +* clang-sys was updated by @eclipseo. [#1539][] +* bindgen should now get include paths correctly even when `--target` is + specified. The `detect_include_paths` option can be used to opt-out of this + behavior. + +[#1535]: https://github.com/rust-lang/rust-bindgen/issues/1535 +[#1537]: https://github.com/rust-lang/rust-bindgen/issues/1537 +[#1540]: https://github.com/rust-lang/rust-bindgen/issues/1540 +[#1492]: https://github.com/rust-lang/rust-bindgen/issues/1492 + +# 0.48.1 + +Released 2019/03/06 + +## Fixed + +* Bindgen will properly lay out types that use reference members. [#1531][] + +[#1531]: https://github.com/rust-lang/rust-bindgen/issues/1531 + +-------------------------------------------------------------------------------- + +# 0.48.0 + +Released 2019/03/04 + +## Changed + +* Default rust target was changed to 1.33, which means that bindgen can get much + more often the layout of structs right. [#1529][] + +## Fixed + +* Bindgen will output repr(align) just when needed for unions. [#1498][] + +[#1529]: https://github.com/rust-lang/rust-bindgen/issues/1529 +[#1498]: https://github.com/rust-lang/rust-bindgen/issues/1498 + +-------------------------------------------------------------------------------- + +# 0.47.4 + +Released 2020/11/13 + +## Added + +* Backported BINDGEN_EXTRA_CLANG_ARGS support per request (#1910). + +-------------------------------------------------------------------------------- + +# 0.47.3 + +Released 2019/02/25 + +## Changed + +* Allowed to build with which 1.0. + +-------------------------------------------------------------------------------- + +# 0.47.2 + +Released 2019/02/22 + +## Fixed + +* @flowbish fixed code generation for nested function prototypes. [#1508][] +* Some complex C++ constructs no longer panic on code generation [#1513][] +* Implicit template parameters are now appended to base classes [#1515][] +* @flier fixed single-argument block pointers [#1519][] +* Bindgen won't panic when parsing an undeduced auto type [#1525][] + +[#1508]: https://github.com/rust-lang/rust-bindgen/issues/1508 +[#1513]: https://github.com/rust-lang/rust-bindgen/issues/1513 +[#1515]: https://github.com/rust-lang/rust-bindgen/issues/1515 +[#1519]: https://github.com/rust-lang/rust-bindgen/issues/1519 +[#1525]: https://github.com/rust-lang/rust-bindgen/issues/1525 + +-------------------------------------------------------------------------------- + +# 0.47.1 + +Released 2019/02/02 + +## Changed + +* @luser improved the error message when rustfmt cannot be found [#1501][] + +## Fixed + +* Reverted `clang-sys` update for regressions [#1505][] + +[#1505]: https://github.com/rust-lang/rust-bindgen/issues/1505 +[#1501]: https://github.com/rust-lang/rust-bindgen/issues/1501 + +-------------------------------------------------------------------------------- + +# 0.47.0 + +Released 2019/01/19 + +## Changed + +- `#pragma pack(n)` is now translated to `#[repr(C, packed(n))]` when targeting Rust 1.33+. [#537][] + +[#537]: https://github.com/rust-lang/rust-bindgen/issues/537 + +* Bitfield enums now use `#[repr(transparent)]` instead of `#[repr(C)]` when targeting Rust 1.28+. [#1474][] + +[#1474]: https://github.com/rust-lang/rust-bindgen/issues/1474 + +## Fixed + +* `#[repr(packed)]` is now properly added if the struct only contains a vtable. + [#1495][] + +[#1495]: https://github.com/rust-lang/rust-bindgen/pull/1495 + +* `clang-sys` should now more accurately find libclang versions when multiple + of them are available. [#1489][] + +[#1489]: https://github.com/rust-lang/rust-bindgen/pull/1489 + +-------------------------------------------------------------------------------- + +# 0.33.1 .. 0.46.0 + +https://github.com/rust-lang/rust-bindgen/compare/v0.32.2...v0.46.0 + +(Just a sneak peek, since a lot of stuff has changed :D) + +## Added + +* APIs to add lines to specific rust modules / C++ namespaces exist now. + [#1307][] + +[#1307]: https://github.com/rust-lang/rust-bindgen/issues/1307 + +## Removed + +* The link options (`link`, `link_framework`, `link_static`) have been removed. + They did nothing already, see [#104][] + +[#104]: https://github.com/rust-lang/rust-bindgen/issues/104 + +## Changed + +* Associated constants are used now for bitfield enums when available. [#1166][] + +[#1166]: https://github.com/rust-lang/rust-bindgen/issues/1166 + +* New versions of a bunch of dependencies (syn / quote / etc.). + +## Fixed + +* Better target information from clang to properly generate types when + cross-compiling [#1289][]. + +[#1289]: https://github.com/rust-lang/rust-bindgen/issues/1289 + +* Pointer constness was fixed in a bunch of cases when using `int const*` and + such. [#1311][] [#1312][]. + +[#1311]: https://github.com/rust-lang/rust-bindgen/issues/1311 +[#1312]: https://github.com/rust-lang/rust-bindgen/issues/1312 + +* Bitfields now work properly on big-endian machines. [#1340][] + +[#1340]: https://github.com/rust-lang/rust-bindgen/issues/1340 + +* `wchar_t` layout works properly now. [#1345][] + +[#1345]: https://github.com/rust-lang/rust-bindgen/issues/1345 + +* Functions can be blacklisted now. [#1364][] + +[#1364]: https://github.com/rust-lang/rust-bindgen/issues/1364 + +* ... Lot's more! + +-------------------------------------------------------------------------------- + +# 0.33.1 + +Released 2018/02/14 + +## Fixed + +* Reverted the dependency update to `quote = "0.4"` and addition of the + `proc_macro2` dependency. The `proc_macro2` crate depends on `rustc` internal + libraries, which means that CLIs which use it must be run under `rustup`, + which is not acceptable for `bindgen`. [#1248][] + +[#1248]: https://github.com/rust-lang/rust-bindgen/issues/1248 + +-------------------------------------------------------------------------------- + +# 0.33.0 -------------------------------------------------------------------------------- @@ -134,12 +1429,12 @@ Released 2018/01/22 * Constified code generation for enums with an explicit type of `bool`. [#1145][] * Bindgen will now call `rustfmt` directly instead of via `rustup`. [#1184][] -[#1197]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1197 -[#1087]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1087 -[#1216]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1216 -[#1224]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1224 -[#1145]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1145 -[#1184]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1184 +[#1197]: https://github.com/rust-lang/rust-bindgen/issues/1197 +[#1087]: https://github.com/rust-lang/rust-bindgen/issues/1087 +[#1216]: https://github.com/rust-lang/rust-bindgen/issues/1216 +[#1224]: https://github.com/rust-lang/rust-bindgen/issues/1224 +[#1145]: https://github.com/rust-lang/rust-bindgen/issues/1145 +[#1184]: https://github.com/rust-lang/rust-bindgen/issues/1184 # 0.32.1 @@ -150,7 +1445,7 @@ Released 2017/12/18 * When translating C/C++ `enum`s into Rust `enum`s using `rustified_enum` / `--rustified-enum`, properly add `#[repr(C)]` to the emitted `enum`. [#1183][] -[#1183]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1183 +[#1183]: https://github.com/rust-lang/rust-bindgen/issues/1183 -------------------------------------------------------------------------------- @@ -225,18 +1520,18 @@ Released 2017/12/08 * In some cases, generated bit-field getters and setters could access memory beyond `self`. This is now fixed. [#954][] -[#1162]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1162 -[#1113]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1113 -[#1112]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1112 -[#1123]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1123 -[#1127]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1127 -[#1136]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1136 -[#1137]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1137 -[#1140]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1140 -[#1146]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1146 -[#1118]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1118 -[#1076]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1076 -[#1158]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1158 +[#1162]: https://github.com/rust-lang/rust-bindgen/issues/1162 +[#1113]: https://github.com/rust-lang/rust-bindgen/issues/1113 +[#1112]: https://github.com/rust-lang/rust-bindgen/issues/1112 +[#1123]: https://github.com/rust-lang/rust-bindgen/issues/1123 +[#1127]: https://github.com/rust-lang/rust-bindgen/issues/1127 +[#1136]: https://github.com/rust-lang/rust-bindgen/issues/1136 +[#1137]: https://github.com/rust-lang/rust-bindgen/issues/1137 +[#1140]: https://github.com/rust-lang/rust-bindgen/issues/1140 +[#1146]: https://github.com/rust-lang/rust-bindgen/issues/1146 +[#1118]: https://github.com/rust-lang/rust-bindgen/issues/1118 +[#1076]: https://github.com/rust-lang/rust-bindgen/issues/1076 +[#1158]: https://github.com/rust-lang/rust-bindgen/issues/1158 -------------------------------------------------------------------------------- @@ -291,12 +1586,12 @@ Released 2017/10/27 programs, we feed those into `bindgen` as headers to generate bindings to, then test that the generated bindings compile and that their layout tests pass. This infrastructure landed in - [many small bits](https://github.com/rust-lang-nursery/rust-bindgen/issues?utf8=%E2%9C%93&q=label%3AA-csmith%20is%3Aclosed). + [many small bits](https://github.com/rust-lang/rust-bindgen/issues?utf8=%E2%9C%93&q=label%3AA-csmith%20is%3Aclosed). We <3 folks who [help us find and fix issues via fuzzing][fuzzing]! *hint hint* -* Added experimental support for the `thiscall` ABI when targetting Rust +* Added experimental support for the `thiscall` ABI when targeting Rust nightly. [#1065][] ## Changed @@ -399,38 +1694,38 @@ Released 2017/10/27 arrays requires program-specific knowledge that `bindgen` cannot have. [#1094][] -[faq]: https://rust-lang-nursery.github.io/rust-bindgen/faq.html -[fuzzing]: https://github.com/rust-lang-nursery/rust-bindgen/blob/master/csmith-fuzzing/README.md - -[#938]: https://github.com/rust-lang-nursery/rust-bindgen/issues/938 -[#888]: https://github.com/rust-lang-nursery/rust-bindgen/issues/888 -[#944]: https://github.com/rust-lang-nursery/rust-bindgen/issues/944 -[#942]: https://github.com/rust-lang-nursery/rust-bindgen/issues/942 -[#947]: https://github.com/rust-lang-nursery/rust-bindgen/issues/947 -[#953]: https://github.com/rust-lang-nursery/rust-bindgen/issues/953 -[#948]: https://github.com/rust-lang-nursery/rust-bindgen/issues/948 -[#925]: https://github.com/rust-lang-nursery/rust-bindgen/issues/925 -[#758]: https://github.com/rust-lang-nursery/rust-bindgen/issues/758 -[#988]: https://github.com/rust-lang-nursery/rust-bindgen/issues/988 -[#987]: https://github.com/rust-lang-nursery/rust-bindgen/issues/987 -[#985]: https://github.com/rust-lang-nursery/rust-bindgen/issues/985 -[#989]: https://github.com/rust-lang-nursery/rust-bindgen/issues/989 -[#1000]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1000 -[#882]: https://github.com/rust-lang-nursery/rust-bindgen/issues/882 -[#884]: https://github.com/rust-lang-nursery/rust-bindgen/issues/884 -[#996]: https://github.com/rust-lang-nursery/rust-bindgen/issues/996 -[#982]: https://github.com/rust-lang-nursery/rust-bindgen/issues/982 -[#1008]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1008 -[#1022]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1022 -[#1048]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1048 -[#1012]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1012 -[#744]: https://github.com/rust-lang-nursery/rust-bindgen/issues/744 -[#1065]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1065 -[#1040]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1040 -[#1029]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1029 -[#1094]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1094 -[#1099]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1099 -[#1105]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1105 +[faq]: https://rust-lang.github.io/rust-bindgen/faq.html +[fuzzing]: https://github.com/rust-lang/rust-bindgen/blob/main/csmith-fuzzing/README.md + +[#938]: https://github.com/rust-lang/rust-bindgen/issues/938 +[#888]: https://github.com/rust-lang/rust-bindgen/issues/888 +[#944]: https://github.com/rust-lang/rust-bindgen/issues/944 +[#942]: https://github.com/rust-lang/rust-bindgen/issues/942 +[#947]: https://github.com/rust-lang/rust-bindgen/issues/947 +[#953]: https://github.com/rust-lang/rust-bindgen/issues/953 +[#948]: https://github.com/rust-lang/rust-bindgen/issues/948 +[#925]: https://github.com/rust-lang/rust-bindgen/issues/925 +[#758]: https://github.com/rust-lang/rust-bindgen/issues/758 +[#988]: https://github.com/rust-lang/rust-bindgen/issues/988 +[#987]: https://github.com/rust-lang/rust-bindgen/issues/987 +[#985]: https://github.com/rust-lang/rust-bindgen/issues/985 +[#989]: https://github.com/rust-lang/rust-bindgen/issues/989 +[#1000]: https://github.com/rust-lang/rust-bindgen/issues/1000 +[#882]: https://github.com/rust-lang/rust-bindgen/issues/882 +[#884]: https://github.com/rust-lang/rust-bindgen/issues/884 +[#996]: https://github.com/rust-lang/rust-bindgen/issues/996 +[#982]: https://github.com/rust-lang/rust-bindgen/issues/982 +[#1008]: https://github.com/rust-lang/rust-bindgen/issues/1008 +[#1022]: https://github.com/rust-lang/rust-bindgen/issues/1022 +[#1048]: https://github.com/rust-lang/rust-bindgen/issues/1048 +[#1012]: https://github.com/rust-lang/rust-bindgen/issues/1012 +[#744]: https://github.com/rust-lang/rust-bindgen/issues/744 +[#1065]: https://github.com/rust-lang/rust-bindgen/issues/1065 +[#1040]: https://github.com/rust-lang/rust-bindgen/issues/1040 +[#1029]: https://github.com/rust-lang/rust-bindgen/issues/1029 +[#1094]: https://github.com/rust-lang/rust-bindgen/issues/1094 +[#1099]: https://github.com/rust-lang/rust-bindgen/issues/1099 +[#1105]: https://github.com/rust-lang/rust-bindgen/issues/1105 -------------------------------------------------------------------------------- @@ -518,18 +1813,18 @@ $ bindgen --rust-target 1.19 * Fixed a regression where template instantiation layout `#[test]`s were being generated with invalid Rust identifiers. [#906][] -[#832]: https://github.com/rust-lang-nursery/rust-bindgen/issues/832 -[#871]: https://github.com/rust-lang-nursery/rust-bindgen/issues/871 -[#874]: https://github.com/rust-lang-nursery/rust-bindgen/pull/874 -[#889]: https://github.com/rust-lang-nursery/rust-bindgen/pull/874 -[#766]: https://github.com/rust-lang-nursery/rust-bindgen/issues/766 -[#876]: https://github.com/rust-lang-nursery/rust-bindgen/issues/876 -[#875]: https://github.com/rust-lang-nursery/rust-bindgen/issues/875 -[#906]: https://github.com/rust-lang-nursery/rust-bindgen/pull/906 -[#900]: https://github.com/rust-lang-nursery/rust-bindgen/issues/900 -[#878]: https://github.com/rust-lang-nursery/rust-bindgen/issues/878 -[#880]: https://github.com/rust-lang-nursery/rust-bindgen/issues/880 -[#927]: https://github.com/rust-lang-nursery/rust-bindgen/issues/927 +[#832]: https://github.com/rust-lang/rust-bindgen/issues/832 +[#871]: https://github.com/rust-lang/rust-bindgen/issues/871 +[#874]: https://github.com/rust-lang/rust-bindgen/pull/874 +[#889]: https://github.com/rust-lang/rust-bindgen/pull/874 +[#766]: https://github.com/rust-lang/rust-bindgen/issues/766 +[#876]: https://github.com/rust-lang/rust-bindgen/issues/876 +[#875]: https://github.com/rust-lang/rust-bindgen/issues/875 +[#906]: https://github.com/rust-lang/rust-bindgen/pull/906 +[#900]: https://github.com/rust-lang/rust-bindgen/issues/900 +[#878]: https://github.com/rust-lang/rust-bindgen/issues/878 +[#880]: https://github.com/rust-lang/rust-bindgen/issues/880 +[#927]: https://github.com/rust-lang/rust-bindgen/issues/927 -------------------------------------------------------------------------------- @@ -539,7 +1834,7 @@ Released 2017/07/31 ## Added -* ["Constified enum modules"](https://github.com/rust-lang-nursery/rust-bindgen/pull/741) +* ["Constified enum modules"](https://github.com/rust-lang/rust-bindgen/pull/741) translating C/C++ `enum`s into constants within a module for namespacing, rather than mangling the name of the generated constants. @@ -585,7 +1880,7 @@ Released 2017/07/31 Use `bindgen::Builder::constified_enum_module` or `--constified-enum-module`. * You can now - [mark particular template instantiations as "opaque"](https://github.com/rust-lang-nursery/rust-bindgen/pull/773), + [mark particular template instantiations as "opaque"](https://github.com/rust-lang/rust-bindgen/pull/773), so that `bindgen` emits a blob of bytes with the correct size and alignment rather than creating generic Rust types. This is useful as a workaround for when a template has a specialization for the given type arguments, which @@ -595,7 +1890,7 @@ Released 2017/07/31 "SomeTemplate"`. * Added the ability to - [preprocess and dump](https://github.com/rust-lang-nursery/rust-bindgen/pull/812) + [preprocess and dump](https://github.com/rust-lang/rust-bindgen/pull/812) the input headers given to `bindgen` to a file. This should make creating reproducible, system independent, standalone test cases much easier! Bring on the new issues! Use `bindgen::Builder::dump_preprocessed_input` or @@ -606,8 +1901,8 @@ Released 2017/07/31 were using an ad-hoc algorithm that had at various times suffered from things like going into infinite loops when coming across cycles. Hopefully those kinds of bugs are a thing of the past! - [#767](https://github.com/rust-lang-nursery/rust-bindgen/issues/767) - [#765](https://github.com/rust-lang-nursery/rust-bindgen/issues/765) + [#767](https://github.com/rust-lang/rust-bindgen/issues/767) + [#765](https://github.com/rust-lang/rust-bindgen/issues/765) ## Changed @@ -618,35 +1913,35 @@ Released 2017/07/31 * No longer generating layout tests for template instantiations using type arguments that we didn't generate bindings for (which then caused compilation - errors). [#679](https://github.com/rust-lang-nursery/rust-bindgen/issues/769) + errors). [#679](https://github.com/rust-lang/rust-bindgen/issues/769) * Fixed function name mangling when cross compiling bindings for - iOS. [#776](https://github.com/rust-lang-nursery/rust-bindgen/pull/776) + iOS. [#776](https://github.com/rust-lang/rust-bindgen/pull/776) * Don't include parent `inline namespace`s' names in types' names. Names of types from some STLs were showing up like `std___cxx11_basic_string` when they should have been - `std_basic_string`. [#789](https://github.com/rust-lang-nursery/rust-bindgen/issues/789) + `std_basic_string`. [#789](https://github.com/rust-lang/rust-bindgen/issues/789) * Fixed a bug where we wouldn't generate type definitions for some types referenced by an opaque type's methods, causing compilation - errors. [#807](https://github.com/rust-lang-nursery/rust-bindgen/issues/807) + errors. [#807](https://github.com/rust-lang/rust-bindgen/issues/807) * Fixed function name mangling issues for win32 - targets. [#819](https://github.com/rust-lang-nursery/rust-bindgen/issues/819) + targets. [#819](https://github.com/rust-lang/rust-bindgen/issues/819) * Fixed a bug where `bindgen` was generating a generic type alias that didn't use its type parameter, which is illegal Rust code and caused compilation - errors. [#820](https://github.com/rust-lang-nursery/rust-bindgen/issues/820) + errors. [#820](https://github.com/rust-lang/rust-bindgen/issues/820) * The generated size, alignment, and field offset unit tests now have stable names rather than sometimes including an internal identifier which is inherently unstable. This was causing unnecessary diffs when folks were checking in new versions of bindings into their VCS. - [#394](https://github.com/rust-lang-nursery/rust-bindgen/issues/394) + [#394](https://github.com/rust-lang/rust-bindgen/issues/394) * Fixed a bug where we would try and `derive(Debug, Default)` on structs that had padding like `[u8; 33]`, which is larger than the largest array length for which Rust will derive traits. This would cause compilation errors when compiling the emitted bindings. - [#648](https://github.com/rust-lang-nursery/rust-bindgen/issues/648) + [#648](https://github.com/rust-lang/rust-bindgen/issues/648) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 995894385b..9c28e198c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,15 +2,17 @@ Hi! We'd love to have your contributions! If you want help or mentorship, reach out to us in a GitHub issue, or stop by -[#servo on irc.mozilla.org](irc://irc.mozilla.org#servo) and introduce yourself. +[#rust on chat.mozilla.org](https://chat.mozilla.org/#/room/#rust:mozilla.org) +and introduce yourself. - - [Code of Conduct](#code-of-conduct) - [Filing an Issue](#filing-an-issue) - [Looking to Start Contributing to `bindgen`?](#looking-to-start-contributing-to-bindgen) +- [Prerequisites](#prerequisites) + - [`rustfmt` / `cargo fmt`](#rustfmt--cargo-fmt) - [Building](#building) - [Testing](#testing) - [Overview](#overview) @@ -23,6 +25,7 @@ out to us in a GitHub issue, or stop by - [Fuzzing `bindgen` with `csmith`](#fuzzing-bindgen-with-csmith) - [Property tests for `bindgen` with `quickchecking`](#property-tests-for-bindgen-with-quickchecking) - [Code Overview](#code-overview) + - [Implementing new options using `syn`](#implementing-new-options-using-syn) - [Pull Requests and Code Reviews](#pull-requests-and-code-reviews) - [Generating Graphviz Dot Files](#generating-graphviz-dot-files) - [Debug Logging](#debug-logging) @@ -30,6 +33,13 @@ out to us in a GitHub issue, or stop by - [Getting `creduce`](#getting-creduce) - [Isolating Your Test Case](#isolating-your-test-case) - [Writing a Predicate Script](#writing-a-predicate-script) +- [Cutting a new bindgen release](#cutting-a-new-bindgen-release) + - [Updating the changelog](#updating-the-changelog) + - [Merge to `main`](#merge-to-main) + - [Tag and publish](#tag-and-publish) + - [Create a new release on Github](#create-a-new-release-on-github) + - [What to do if a Github release fails](#what-to-do-if-a-github-release-fails) + - [Create a new crates.io release](#create-a-new-cratesio-release) @@ -37,70 +47,72 @@ out to us in a GitHub issue, or stop by We abide by the [Rust Code of Conduct][coc] and ask that you do as well. -[coc]: https://www.rust-lang.org/en-US/conduct.html +[coc]: https://www.rust-lang.org/policies/code-of-conduct ## Filing an Issue Think you've found a bug? File an issue! To help us understand and reproduce the issue, provide us with: -* A (preferably reduced) C/C++ header file that reproduces the issue -* The `bindgen` flags used to reproduce the issue with the header file -* The expected `bindgen` output -* The actual `bindgen` output -* The [debugging logs](#logs) generated when running `bindgen` on this testcase +- A (preferably reduced) C/C++ header file that reproduces the issue +- The `bindgen` flags used to reproduce the issue with the header file +- The expected `bindgen` output +- The actual `bindgen` output +- The [debugging logs](#debug-logging) generated when running `bindgen` on this testcase ## Looking to Start Contributing to `bindgen`? -* [Issues labeled "easy"](https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy) -* [Issues labeled "less easy"](https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy) -* [Issues labeled "help wanted"](https://github.com/rust-lang-nursery/rust-bindgen/labels/help%20wanted) -* Still can't find something to work on? [Drop a comment here](https://github.com/rust-lang-nursery/rust-bindgen/issues/747) +- [Issues labeled "easy"](https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy) +- [Issues labeled "less easy"](https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy) +- [Issues labeled "help wanted"](https://github.com/rust-lang/rust-bindgen/labels/help%20wanted) +- Still can't find something to work on? [Drop a comment here](https://github.com/rust-lang/rust-bindgen/issues/747) + +## Prerequisites + +### `rustfmt` / `cargo fmt` + +We use `nightly` channel for `rustfmt`, +so please set the appropriate setting in your editor/IDE for that. + +For rust-analyzer, you can set `rustfmt.extraArgs = ['+nightly']`. + +To check via command line, you can run `cargo +nightly fmt --check`. ## Building To build the `bindgen` library and the `bindgen` executable: -``` -$ cargo build +```sh +cargo build ``` If you installed multiple versions of llvm, it may not be able to locate the -latest version of libclang. In that case, you may want to either uninstall other -versions of llvm, or specify the path of the desired libclang explicitly: +latest version of `libclang`. In that case, you may want to either uninstall other +versions of llvm, or specify the path of the desired `libclang` explicitly: -``` -$ export LIBCLANG_PATH=path/to/clang-3.9/lib -``` - -Additionally, you may want to build and test with the `testing_only_docs` -feature to ensure that you aren't forgetting to document types and functions. CI -will catch it if you forget, but the turn around will be a lot slower ;) - -``` -$ cargo build --features testing_only_docs +```sh +export LIBCLANG_PATH=path/to/clang-9.0/lib ``` ## Testing ### Overview -Input C/C++ test headers reside in the `tests/headers` directory. Expected -output Rust bindings live in `tests/expectations/tests`. For example, -`tests/headers/my_header.h`'s expected generated Rust bindings would be -`tests/expectations/tests/my_header.rs`. +Input C/C++ test headers reside in the `bindgen-tests/tests/headers` directory. Expected +output Rust bindings live in `bindgen-tests/tests/expectations/tests`. For example, +`bindgen-tests/tests/headers/my_header.h`'s expected generated Rust bindings would be +`bindgen-tests/tests/expectations/tests/my_header.rs`. There are also some integration tests in the `./bindgen-integration` crate, which uses `bindgen` to generate bindings to some C++ code, and then uses the bindings, asserting that values are what we expect them to be, both on the Rust and C++ side. -The generated and expected bindings are run through `rustfmt` before they are -compared. Make sure you have `rustfmt` up to date: - -``` -$ rustup update nightly -$ rustup run nightly cargo install -f rustfmt-nightly -``` +The generated and expected bindings are formatted with [`prettyplease`] before they are +compared. It is a default (but optional) dependency of `bindgen`, +so be sure to keep that in mind +(if you built `bindgen` with the `--no-default-features` option of Cargo). +Note also that `rustfmt` formatting is disabled for the `bindgen-tests/tests/expectations/` +directory tree, which helps avoid failing ui tests. Note: running `cargo test` from the root directory of `bindgen`'s repository does not automatically test the generated bindings or run the integration tests. @@ -108,40 +120,60 @@ These steps must be performed manually when needed. ### Testing Bindings Generation -To regenerate bindings from the corpus of test headers in `tests/headers` and -compare them against the expected bindings in `tests/expectations/tests`, run: +To regenerate bindings from the corpus of test headers in `bindgen-tests/tests/headers` and +compare them against the expected bindings in `bindgen-tests/tests/expectations/tests`, run: -``` -$ cargo test +```sh +cargo test ``` As long as you aren't making any changes to `bindgen`'s output, running this should be sufficient to test your local modifications. +You may set the `BINDGEN_OVERWRITE_EXPECTED` environment variable to overwrite +the expected bindings with `bindgen`'s current output: + +```sh +BINDGEN_OVERWRITE_EXPECTED=1 cargo test +``` + +If you set the `BINDGEN_TESTS_DIFFTOOL` environment variable, `cargo test` will +execute `BINDGEN_TESTS_DIFFTOOL /path/of/expected/output /path/of/actual/output` +when the expected output differs from the actual output. You can use this to +hand check differences by setting it to e.g. "meld" (assuming you have meld +installed). + +If you're not changing command line arguments, you may want to set +`BINDGEN_DISABLE_ROUNDTRIP_TEST` to avoid a lot of tests for round-tripping of +those. + ### Testing Generated Bindings If your local changes are introducing expected modifications in the -`tests/expectations/tests/*` bindings files, then you should test that the +`bindgen-tests/tests/expectations/tests/*` bindings files, then you should test that the generated bindings files still compile, and that their struct layout tests still pass. Also, run the integration tests (see below). You can do this with these commands: -``` -$ cd tests/expectations -$ cargo test +```sh +cd bindgen-tests/tests/expectations +cargo test ``` ### Testing a Single Header's Bindings Generation and Compiling its Bindings -Sometimes its useful to work with one test header from start (generating +Note: You will need to install [graphviz](https://graphviz.org/) since that +is a dependency for running `test-one.sh`. + +Sometimes it's useful to work with one test header from start (generating bindings for it) to finish (compiling the bindings and running their layout -tests). This can be done with the `tests/test-one.sh` script. It supports fuzzy +tests). This can be done with the `bindgen-tests/tests/test-one.sh` script. It supports fuzzy searching for test headers. For example, to test `tests/headers/what_is_going_on.hpp`, execute this command: -``` -$ ./tests/test-one.sh going +```sh +./bindgen-tests/tests/test-one.sh going ``` Note that `test-one.sh` does not recompile `bindgen`, so if you change the code, @@ -149,9 +181,9 @@ you'll need to rebuild it before running the script again. ### Authoring New Tests -To add a new test header to the suite, simply put it in the `tests/headers` +To add a new test header to the suite, simply put it in the `bindgen-tests/tests/headers` directory. Next, run `bindgen` to generate the initial expected output Rust -bindings. Put those in `tests/expectations/tests`. +bindings. Put those in `bindgen-tests/tests/expectations/tests`. If your new test requires certain flags to be passed to `bindgen`, you can specify them at the top of the test header, with a comment like this: @@ -164,9 +196,9 @@ specify them at the top of the test header, with a comment like this: Then verify the new Rust bindings compile and pass their layout tests: -``` -$ cd tests/expectations -$ cargo test new_test_header +```sh +cd bindgen-tests/tests/expectations +cargo test new_test_header ``` ### Test Expectations and `libclang` Versions @@ -174,17 +206,16 @@ $ cargo test new_test_header If a test generates different bindings across different `libclang` versions (for example, because we take advantage of better/newer APIs when possible), then you can add multiple test expectations, one for each supported `libclang` -version. Instead of having a single `tests/expectations/tests/my_test.rs` file, +version. Instead of having a single `bindgen-tests/tests/expectations/tests/my_test.rs` file, add each of: -* `tests/expectations/tests/libclang-4/my_test.rs` -* `tests/expectations/tests/libclang-3.9/my_test.rs` -* `tests/expectations/tests/libclang-3.8/my_test.rs` +- `bindgen-tests/tests/expectations/tests/libclang-16/my_test.rs` +- `bindgen-tests/tests/expectations/tests/libclang-9/my_test.rs` If you need to update the test expectations for a test file that generates different bindings for different `libclang` versions, you *don't* need to have -many version of `libclang` installed locally. Just make a work-in-progress pull -request, and then when Travis CI fails, it will log a diff of the +many versions of `libclang` installed locally. Just make a work-in-progress pull +request, and then when CI fails, it will log a diff of the expectations. Use the diff to patch the appropriate expectation file locally and then update your pull request. @@ -192,15 +223,9 @@ Usually, `bindgen`'s test runner can infer which version of `libclang` you have. If for some reason it can't, you can force a specific `libclang` version to check the bindings against with a cargo feature: +```sh +cargo test --features __testing_only_libclang_$VERSION ``` -$ cargo test --features testing_only_libclang_$VERSION -``` - -Where `$VERSION` is one of: - -* `4` -* `3_9` -* `3_8` depending on which version of `libclang` you have installed. @@ -212,9 +237,9 @@ values are what we expect them to be, both on the Rust and C++ side. To run the integration tests, issue the following: -``` -$ cd bindgen-integration -$ cargo test +```sh +cd bindgen-integration +cargo test ``` ### Fuzzing `bindgen` with `csmith` @@ -229,9 +254,9 @@ See [./csmith-fuzzing/README.md](./csmith-fuzzing/README.md) for details. The `tests/quickchecking` crate generates property tests for `bindgen`. From the crate's directory you can run the tests with `cargo run`. For details -on additional configuration including how to preserve / inspect the generated -property tests, see -[./tests/quickchecking/README.md](./tests/quickchecking/README.md). +on additional configuration including how to preserve / inspect the generated +property tests, see +[`./tests/quickchecking/README.md`](./tests/quickchecking/README.md). ## Code Overview @@ -248,38 +273,40 @@ The umbrella IR type is the `Item`. It contains various nested `enum`s that let us drill down and get more specific about the kind of construct that we're looking at. Here is a summary of the IR types and their relationships: -* `Item` contains: - * An `ItemId` to uniquely identify it. - * An `ItemKind`, which is one of: - * A `Module`, which is originally a C++ namespace and becomes a Rust +- `Item` contains: + - An `ItemId` to uniquely identify it. + - An `ItemKind`, which is one of: + - A `Module`, which is originally a C++ namespace and becomes a Rust module. It contains the set of `ItemId`s of `Item`s that are defined within it. - * A `Type`, which contains: - * A `Layout`, describing the type's size and alignment. - * A `TypeKind`, which is one of: - * Some integer type. - * Some float type. - * A `Pointer` to another type. - * A function pointer type, with `ItemId`s of its parameter types + - A `Type`, which contains: + - A `Layout`, describing the type's size and alignment. + - A `TypeKind`, which is one of: + - Some integer type. + - Some float type. + - A `Pointer` to another type. + - A function pointer type, with `ItemId`s of its parameter types and return type. - * An `Alias` to another type (`typedef` or `using X = ...`). - * A fixed size `Array` of `n` elements of another type. - * A `Comp` compound type, which is either a `struct`, `class`, + - An `Alias` to another type (`typedef` or `using X = ...`). + - A fixed size `Array` of `n` elements of another type. + - A `Comp` compound type, which is either a `struct`, `class`, or `union`. This is potentially a template definition. - * A `TemplateInstantiation` referencing some template definition + - A `TemplateInstantiation` referencing some template definition and a set of template argument types. - * Etc... - * A `Function`, which contains: - * An ABI - * A mangled name - * a `FunctionKind`, which describes whether this function is a plain + - Etc... + - A `Function`, which contains: + - An ABI + - A mangled name + - a `FunctionKind`, which describes whether this function is a plain function, method, static method, constructor, destructor, etc. - * The `ItemId` of its function pointer type. - * A `Var` representing a static variable or `#define` constant, which + - The `ItemId` of its function pointer type. + - A `Var` representing a static variable or `#define` constant, which contains: - * Its type's `ItemId` - * Optionally, a mangled name - * Optionally, a value + - Its type's `ItemId` + - Optionally, a mangled name + - Optionally, a value + - An optional `clang::SourceLocation` that holds the first source code + location where the `Item` was encountered. The IR forms a graph of interconnected and inter-referencing types and functions. The `ir::traversal` module provides IR graph traversal @@ -295,14 +322,26 @@ parameters a given type uses. The analyses are defined in `ir::analysis::MonotoneFramework` trait. The final phase is generating Rust source text from the analyzed IR, and it is -defined in `src/codegen/*`. We use the `quote` crate, which provides the `quote! -{ ... }` macro for quasi-quoting Rust forms. +defined in `src/codegen/*`. We use the `quote` crate, which provides the `quote!{ ... }` +macro for quasi-quoting Rust forms. Some options that affect the +generated Rust code are implemented using the [`syn`](https://docs.rs/syn) crate. + +### Implementing new options using `syn` + +If a new option can be implemented using the `syn` crate it should be added to +the `codegen::postprocessing` module by following these steps: + +- Introduce a new field to `BindgenOptions` for the option. +- Write a free function inside `codegen::postprocessing` implementing the + option. This function with the same name of the `BindgenOptions` field. +- Add a new value to the `codegen::postprocessing::PASSES` for the option using + the `pass!` macro. ## Pull Requests and Code Reviews Ensure that each commit stands alone, and passes tests. This enables better `git bisect`ing when needed. If your commits do not stand on their own, then rebase -them on top of the latest master and squash them into a single commit. +them on top of the latest main and squash them into a single commit. All pull requests undergo code review before merging. To request review, comment `r? @github_username_of_reviewer`. They we will respond with `r+` to approve the @@ -311,14 +350,13 @@ changes should be squashed into the original commit. Unsure who to ask for review? Ask any of: -* `@emilio` -* `@fitzgen` -* `@pepyakin` +- `@emilio` +- `@pvdrz` More resources: -* [Servo's GitHub Workflow](https://github.com/servo/servo/wiki/Github-workflow) -* [Beginner's Guide to Rebasing and Squashing](https://github.com/servo/servo/wiki/Beginner's-guide-to-rebasing-and-squashing) +- [Servo's GitHub Workflow](https://github.com/servo/servo/wiki/Github-workflow) +- [Beginner's Guide to Rebasing and Squashing](https://github.com/servo/servo/wiki/Beginner's-guide-to-rebasing-and-squashing) ## Generating Graphviz Dot Files @@ -329,22 +367,22 @@ debugging bindgen! First, make sure you have Graphviz and `dot` installed: -``` -$ brew install graphviz # OS X -$ sudo dnf install graphviz # Fedora -$ # Etc... +```sh +brew install graphviz # OS X +sudo dnf install graphviz # Fedora +# Etc... ``` Then, use the `--emit-ir-graphviz` flag to generate a `dot` file from our IR: -``` -$ cargo run -- example.hpp --emit-ir-graphviz output.dot +```sh +cargo run -- example.hpp --emit-ir-graphviz output.dot ``` Finally, convert the `dot` file to an image: -``` -$ dot -Tpng output.dot -o output.png +```sh +dot -Tpng output.dot -o output.png ``` The final result will look something like this: @@ -356,14 +394,14 @@ The final result will look something like this: To help debug what `bindgen` is doing, you can define the environment variable `RUST_LOG=bindgen` to get a bunch of debugging log spew. -``` -$ RUST_LOG=bindgen ./target/debug/bindgen [flags...] ~/path/to/some/header.h +```sh +RUST_LOG=bindgen ./target/debug/bindgen [flags...] ~/path/to/some/header.h ``` This logging can also be used when debugging failing tests: -``` -$ RUST_LOG=bindgen cargo test +```sh +RUST_LOG=bindgen cargo test ``` ## Using `creduce` to Minimize Test Cases @@ -380,13 +418,13 @@ that same bad behavior. Often, you can install `creduce` from your OS's package manager: -``` -$ sudo apt install creduce -$ brew install creduce -$ # Etc... +```sh +sudo apt install creduce +brew install creduce +# Etc... ``` -[Otherwise, follow these instructions for building and/or installing `creduce`.](https://github.com/csmith-project/creduce/blob/master/INSTALL) +Otherwise, follow [these instructions](https://github.com/csmith-project/creduce/blob/master/INSTALL.md) for building and/or installing `creduce`. Running `creduce` requires two things: @@ -397,7 +435,9 @@ Running `creduce` requires two things: With those two things in hand, running `creduce` looks like this: - $ creduce ./predicate.sh ./isolated-test-case.h +```sh +creduce ./predicate.sh ./isolated-test-case.h +``` ### Isolating Your Test Case @@ -451,10 +491,11 @@ to fail to compile `bindgen`'s emitted bindings, you can invoke `predicate.py` like this: ```bash +# the rustc-grep argument expects a regex, thus escape where necessary path/to/rust-bindgen/csmith-fuzzing/predicate.py \ --bindings-grep NameOfTheStructThatIsErroneouslyDerivingEq \ --expect-compile-fail \ - --rustc-grep 'error[E0277]: the trait bound `f64: std::cmp::Eq` is not satisfied' \ + --rustc-grep 'error\[E0277\]: the trait bound `f64: std::cmp::Eq` is not satisfied' \ ./isolated-test-case.h ``` @@ -471,8 +512,8 @@ path/to/rust-bindgen/csmith-fuzzing/predicate.py \ For details on all the flags that you can pass to `predicate.py`, run: -``` -$ path/to/rust-bindgen/csmith-fuzzing/predicate.py --help +```sh +path/to/rust-bindgen/csmith-fuzzing/predicate.py --help ``` And you can always write your own, arbitrary predicate script if you prefer. @@ -485,3 +526,101 @@ case down to 5 lines. Happy bug hunting and test case reducing! [More information on using `creduce`.](https://embed.cs.utah.edu/creduce/using/) + +## Cutting a new bindgen release + +To cut a release, the following needs to happen: + +### Updating the changelog + +Update the CHANGELOG.md file with the changes from the last release. Something +like the following is a useful way to check what has landed: + +```sh +git log --oneline v0.62.0..HEAD +``` + +Also worth checking the [next-release +tag](https://github.com/rust-lang/rust-bindgen/pulls?q=is%3Apr+label%3Anext-release). +It is very important that you do not rename the `Unreleased` section of the +changelog as this will be done automatically using `cargo release` on a further +step. + +### Merge to `main` + +For regular releases, the changes above should end up in `main` before +publishing. For dot-releases of an old version (e.g., cherry-picking an +important fix) you can skip this. + +### Tag and publish + +Once you're in `main`. Remember to install `doctoc` by running: + +```sh +npm install doctoc +``` + +And then run: + +```sh +cargo release [patch|minor] --no-publish --execute +``` + +This does the following: + +- Bump the version. +- Turn the `Unreleased` section of the changelog into the section for the version being released. +- Update the table of contents of the changelog using `doctoc`. +- Tag (`git tag`) the HEAD commit +- Push (`git push`) to GitHub + +The `patch` and `minor` refer to semver concepts: + +- `patch` would bump **v0.68.1** to **v0.68.2** +- `minor` would bump **v0.68.2** to **v0.69.0** + +> NOTE: +> We use the `--no-publish` so that the crates are only published after the release is complete. +> This is automatic, provided the release CI job is successful. + +### Create a new release on Github + +The release is automated with the help of `.github/workflows/release.yml`, +and will only be created... + +- when a Git tag is pushed +- when all tests succeed + +While the tests are still running, +a draft GitHub release will be created, +to avoid notifying watchers of the repo should a CI step fail. + +If everything succeeds, +tarballs containing bindgen cli executables for Linux and MacOS +(both for x86 and Arm) will be created. +See `[workspace.metadata.dist]` section in `Cargo.toml` for the configuration. + +To update the release configuration, +when a new `cargo-dist` is available: + +```sh +cargo dist init # from "cargo install cargo-dist" +``` + +### What to do if a Github release fails + +If the release process fails after you run `cargo release`, you can manually +delete the tag and release from Github. Also remember to delete the tag locally +by running `git tag -d`. Once all the extra changes are in the `main` branch, +you can trigger a release by creating a new tag using `git tag` and push it +using `git push --tag`. + +### Create a new crates.io release + +Go to [the Publish +workflow](https://github.com/rust-lang/rust-bindgen/actions/workflows/publish.yml) +and run a new workflow using the "Run Workflow" button. + +Remember that crates.io releases cannot be deleted! + +[`prettyplease`]: https://github.com/dtolnay/prettyplease diff --git a/Cargo.lock b/Cargo.lock index 71e001173c..28bc2732ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,437 +1,737 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" -version = "0.6.3" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] -name = "ansi_term" -version = "0.9.0" +name = "annotate-snippets" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] [[package]] -name = "atty" -version = "0.2.2" +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", ] [[package]] name = "bindgen" -version = "0.36.0" +version = "0.72.0" +dependencies = [ + "annotate-snippets", + "bitflags", + "cexpr", + "clang-sys", + "clap", + "clap_complete", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bindgen-cli" +version = "0.72.0" +dependencies = [ + "bindgen", + "env_logger 0.10.2", + "log", + "proc-macro2", + "shlex", +] + +[[package]] +name = "bindgen-integration" +version = "0.1.0" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "bindgen-tests" +version = "0.1.0" dependencies = [ - "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "which 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen", + "owo-colors", + "prettyplease", + "proc-macro2", + "regex", + "shlex", + "similar", + "syn", + "tempfile", ] [[package]] name = "bitflags" -version = "0.8.2" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "cc" -version = "1.0.6" +version = "1.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +dependencies = [ + "shlex", +] [[package]] name = "cexpr" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "nom", ] [[package]] name = "cfg-if" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] -name = "chrono" -version = "0.4.0" +name = "clang-sys" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "glob", + "libc", + "libloading", ] [[package]] -name = "clang-sys" -version = "0.22.0" +name = "clap" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap_builder", + "clap_derive", ] [[package]] -name = "clap" -version = "2.24.2" +name = "clap_builder" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "diff" -version = "0.1.10" +name = "clap_complete" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "log", + "regex", +] [[package]] name = "env_logger" -version = "0.5.3" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "glob" -version = "0.2.11" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "humantime" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" + +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "windows-sys", ] [[package]] -name = "lazy_static" -version = "1.0.0" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] [[package]] name = "libc" -version = "0.2.39" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libloading" -version = "0.5.0" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ - "cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "windows-targets", ] +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "log" -version = "0.4.1" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "malloc_buf" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "memchr" -version = "1.0.1" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", + "minimal-lexical", ] [[package]] -name = "nom" -version = "1.2.4" +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "owo-colors" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" [[package]] -name = "num" -version = "0.1.42" +name = "prettyplease" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "syn", ] [[package]] -name = "num-integer" -version = "0.1.36" +name = "proc-macro2" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ - "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident", ] [[package]] -name = "num-iter" -version = "0.1.35" +name = "quickcheck" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger 0.8.4", + "log", + "rand", +] + +[[package]] +name = "quickchecking" +version = "0.0.0" dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "quickcheck", + "tempfile", ] [[package]] -name = "num-traits" -version = "0.2.0" +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "proc-macro2" -version = "0.3.2" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core", ] [[package]] -name = "quote" -version = "0.5.1" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "proc-macro2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.2.16", ] [[package]] -name = "redox_syscall" -version = "0.1.37" +name = "regex" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] [[package]] -name = "regex" -version = "0.2.2" +name = "regex-automata" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] [[package]] name = "shlex" -version = "0.1.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "strsim" -version = "0.6.0" +name = "similar" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] -name = "term_size" -version = "0.3.0" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "termcolor" -version = "0.3.4" +name = "syn" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ - "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "thread-id" -version = "3.1.0" +name = "tempfile" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys", ] [[package]] -name = "thread_local" -version = "0.3.3" +name = "termcolor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ - "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] -name = "time" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "tests_expectations" +version = "0.0.0" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block", + "libloading", + "objc", ] [[package]] -name = "unicode-segmentation" -version = "1.2.0" +name = "unicode-ident" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] -name = "unicode-xid" -version = "0.1.0" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "unreachable" -version = "0.1.1" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "utf8-ranges" -version = "1.0.0" +name = "wasi" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] -name = "vec_map" -version = "0.8.0" +name = "winapi-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] [[package]] -name = "void" -version = "1.0.2" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] [[package]] -name = "which" -version = "1.0.2" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] -name = "winapi" -version = "0.2.8" +name = "windows_aarch64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "winapi" -version = "0.3.4" +name = "windows_aarch64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "winapi-build" -version = "0.1.1" +name = "windows_i686_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_i686_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "wincolor" -version = "0.1.6" +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49" -"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d" -"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" -"checksum clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" -"checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" -"checksum env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f15f0b172cb4f52ed5dbf47f774a387cd2315d1bf7894ab5af9b083ae27efa5a" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" -"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" -"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" -"checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10" -"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -"checksum proc-macro2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "681c2c8e039ff358cb926dbc5151d561cbd0249089986ace39dfe8e405bb7511" -"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" -"checksum termcolor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "73e83896da740a4541a6f21606b35f2aa4bada5b65d89dc61114bf9d6ff2dc7e" -"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum which 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d238435618c0f298d2d75596c2d4fa7d4ea469c0c1c3ff824737ed50ad5ab61c" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" + "bitflags", +] diff --git a/Cargo.toml b/Cargo.toml index a9f2bdc6cf..edb0d35371 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,78 +1,98 @@ -[package] -authors = [ - "Jyun-Yan You ", - "Emilio Cobos Álvarez ", - "Nick Fitzgerald ", - "The Servo project developers", +[workspace] +resolver = "2" +members = [ + "bindgen", + "bindgen-cli", + "bindgen-integration", + "bindgen-tests", + "bindgen-tests/tests/quickchecking", + "bindgen-tests/tests/expectations", ] -description = "Automatically generates Rust FFI bindings to C and C++ libraries." -keywords = ["bindings", "ffi", "code-generation"] -categories = ["external-ffi-bindings", "development-tools::ffi"] -license = "BSD-3-Clause" -name = "bindgen" -readme = "README.md" -repository = "https://github.com/rust-lang-nursery/rust-bindgen" -documentation = "https://docs.rs/bindgen" -homepage = "https://rust-lang-nursery.github.io/rust-bindgen/" -version = "0.36.0" -build = "build.rs" - -include = [ - "LICENSE", - "README.md", - "Cargo.toml", - "build.rs", - "src/*.rs", - "src/**/*.rs", +default-members = [ + "bindgen", + "bindgen-cli", + "bindgen-tests", ] -[badges] -travis-ci = { repository = "rust-lang-nursery/rust-bindgen" } +[workspace.package] +# If you change this, also update README.md +rust-version = "1.70.0" +edition = "2021" -[lib] -path = "src/lib.rs" +# All dependency version management is centralized here +[workspace.dependencies] +annotate-snippets = "0.11.4" +bindgen = { version = "0.72.0", path = "./bindgen", default-features = false } +bitflags = "2.2.1" +block = "0.1" +cc = "1.0" +cexpr = "0.6" +clang-sys = "1" +clap = "4" +clap_complete = "4" +env_logger = "0.10.0" +itertools = { version = ">=0.10,<0.15", default-features = false } +libloading = "0.8" +log = "0.4" +objc = "0.2" +owo-colors = "4.1.0" +prettyplease = "0.2.7" +proc-macro2 = "1.0.80" +quickcheck = "1.0" +quote = { version = "1", default-features = false } +regex = { version = "1.5.3", default-features = false } +rustc-hash = "2.1.0" +shlex = "1" +similar = "2.2.1" +syn = "2.0" +tempfile = "3" -[[bin]] -name = "bindgen" -path = "src/main.rs" -doc = false +[workspace.lints.rust] +unused_qualifications = "warn" -[dev-dependencies] -diff = "0.1" -clap = "2" -shlex = "0.1" +[workspace.lints.clippy] +pedantic = { level = "warn", priority = -1 } -[dependencies] -cexpr = "0.2" -cfg-if = "0.1.0" -# This kinda sucks: https://github.com/rust-lang/cargo/issues/1982 -clap = "2" -clang-sys = { version = "0.22.0", features = ["runtime", "clang_6_0"] } -lazy_static = "1" -peeking_take_while = "0.1.2" -quote = { version = "0.5", default-features = false } -regex = "0.2" -which = "1.0.2" -proc-macro2 = { version = "0.3.2", default-features = false } +cast_possible_truncation = "allow" +cast_possible_wrap = "allow" +cast_precision_loss = "allow" +cast_sign_loss = "allow" +default_trait_access = "allow" +ignored_unit_patterns = "allow" +implicit_hasher = "allow" +items_after_statements = "allow" +match_same_arms = "allow" +maybe_infinite_iter = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" +module_name_repetitions = "allow" +must_use_candidate = "allow" +redundant_closure_for_method_calls = "allow" +return_self_not_must_use = "allow" +similar_names = "allow" +struct_excessive_bools = "allow" +struct_field_names = "allow" +unnecessary_wraps = "allow" +unreadable_literal = "allow" +used_underscore_binding = "allow" +wildcard_imports = "allow" -[dependencies.env_logger] -optional = true -version = "0.5" +# TODO +trivially_copy_pass_by_ref = "allow" +unused_self = "allow" -[dependencies.log] -optional = true -version = "0.4" +# Theese seem to be ok to ignore for now +enum_glob_use = "allow" +too_many_lines = "allow" -[features] -default = ["logging"] -logging = ["env_logger", "log"] -static = [] +# Config for 'cargo release' +[workspace.metadata.release] +shared-version = true # ensures published packages share the same version +tag-name = "v{{version}}" +# Don't release any crate unless its manifest has `release = true` +release = false -# These features only exist for CI testing -- don't use them if you're not hacking -# on bindgen! -testing_only_docs = [] -testing_only_extra_assertions = [] -testing_only_libclang_5 = [] -testing_only_libclang_4 = [] -testing_only_libclang_3_9 = [] -testing_only_libclang_3_8 = [] +# The profile that 'cargo dist' will build with +[profile.dist] +inherits = "release" +lto = "thin" diff --git a/LICENSE b/LICENSE index 589b5326e6..62f55f45a1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,28 +1,29 @@ -Copyright (c) 2013, Jyun-Yan You +BSD 3-Clause License +Copyright (c) 2013, Jyun-Yan You All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the author nor the names of his contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 27cefbffc9..b35dee3bef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# `bindgen` +[![crates.io](https://img.shields.io/crates/v/bindgen.svg)](https://crates.io/crates/bindgen) +[![docs.rs](https://docs.rs/bindgen/badge.svg)](https://docs.rs/bindgen/) -[`impl period`](https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html) has been started! Join us at [Gitter.im](https://gitter.im/rust-impl-period/WG-dev-tools-bindgen). +# `bindgen` **`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.** @@ -19,7 +20,7 @@ void eleven_out_of_ten_majestic_af(Doggo* pupper); functions and use its types: ```rust -/* automatically generated by rust-bindgen */ +/* automatically generated by rust-bindgen 0.99.9 */ #[repr(C)] pub struct Doggo { @@ -34,12 +35,55 @@ extern "C" { ## Users Guide -[📚 Read the `bindgen` users guide here! 📚](https://rust-lang-nursery.github.io/rust-bindgen) +[📚 Read the `bindgen` users guide here! 📚](https://rust-lang.github.io/rust-bindgen) + +## MSRV + +The `bindgen` minimum supported Rust version is **1.70.0**. + +The `bindgen-cli` minimum supported Rust version is **1.70.0**. + +No MSRV bump policy has been established yet, so MSRV may increase in any release. + +The MSRV is the minimum Rust version that can be used to *compile* each crate. However, `bindgen` and `bindgen-cli` can generate bindings that are compatible with Rust versions below the current MSRV. + +Most of the time, the `bindgen-cli` crate will have a more recent MSRV than `bindgen` as crates such as `clap` require it. ## API Reference [API reference documentation is on docs.rs](https://docs.rs/bindgen) +## Environment Variables + +In addition to the [library API](https://docs.rs/bindgen) and [executable command-line API][bindgen-cmdline], +`bindgen` can be controlled through environment variables. + +End-users should set these environment variables to modify `bindgen`'s behavior without modifying the source code of direct consumers of `bindgen`. + +- `BINDGEN_EXTRA_CLANG_ARGS`: extra arguments to pass to `clang` + - Arguments are whitespace-separated + - Use shell-style quoting to pass through whitespace + - Examples: + - Specify alternate sysroot: `--sysroot=/path/to/sysroot` + - Add include search path with spaces: `-I"/path/with spaces"` +- `BINDGEN_EXTRA_CLANG_ARGS_`: similar to `BINDGEN_EXTRA_CLANG_ARGS`, + but used to set per-target arguments to pass to clang. Useful to set system include + directories in a target-specific way in cross-compilation environments with multiple targets. + Has precedence over `BINDGEN_EXTRA_CLANG_ARGS`. + +Additionally, `bindgen` uses `libclang` to parse C and C++ header files. +To modify how `bindgen` searches for `libclang`, see the [`clang-sys` documentation][clang-sys-env]. +For more details on how `bindgen` uses `libclang`, see the [`bindgen` users guide][bindgen-book-clang]. + +## Releases + +We don't follow a specific release calendar, but if you need a release please +file an issue requesting that (ping `@emilio` for increased effectiveness). + ## Contributing [See `CONTRIBUTING.md` for hacking on `bindgen`!](./CONTRIBUTING.md) + +[bindgen-cmdline]: https://rust-lang.github.io/rust-bindgen/command-line-usage.html +[clang-sys-env]: https://github.com/KyleMayes/clang-sys#environment-variables +[bindgen-book-clang]: https://rust-lang.github.io/rust-bindgen/requirements.html#clang diff --git a/appveyor.yml b/appveyor.yml index 91009f68f6..ffb74eedc6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,23 +3,17 @@ environment: RUST_CHANNEL: "%Configuration%" matrix: - TARGET: gnu - LLVM_VERSION: 3.9.0-2 - BINDGEN_FEATURES: testing_only_libclang_3_9 + LLVM_VERSION: 9.0.0-1 + BINDGEN_FEATURES: __testing_only_libclang_9 - TARGET: gnu - LLVM_VERSION: 4.0.0-1 - BINDGEN_FEATURES: testing_only_libclang_4 + LLVM_VERSION: 16.0.4 + BINDGEN_FEATURES: __testing_only_libclang_16 - TARGET: msvc - LLVM_VERSION: 5.0.0-1 - BINDGEN_FEATURES: testing_only_libclang_5 + LLVM_VERSION: 9.0.0 + BINDGEN_FEATURES: __testing_only_libclang_9 - TARGET: msvc - LLVM_VERSION: 3.9.0 - BINDGEN_FEATURES: testing_only_libclang_3_9 - - TARGET: msvc - LLVM_VERSION: 4.0.0 - BINDGEN_FEATURES: testing_only_libclang_4 - - TARGET: msvc - LLVM_VERSION: 5.0.0 - BINDGEN_FEATURES: testing_only_libclang_5 + LLVM_VERSION: 16.0.4 + BINDGEN_FEATURES: __testing_only_libclang_16 configuration: - stable @@ -31,7 +25,7 @@ platform: branches: only: - - master + - main install: - if %PLATFORM% == x86 (set RUST_PLATFORM=i686&set MINGW_BITS=32) else (set RUST_PLATFORM=x86_64&set MINGW_BITS=64) diff --git a/bindgen-cli/Cargo.toml b/bindgen-cli/Cargo.toml new file mode 100644 index 0000000000..e5d49a6ecc --- /dev/null +++ b/bindgen-cli/Cargo.toml @@ -0,0 +1,49 @@ +lints.workspace = true + +[package] +authors = [ + "The rust-bindgen project contributors", +] +description = "Automatically generates Rust FFI bindings to C and C++ libraries." +keywords = ["bindings", "ffi", "code-generation"] +categories = ["external-ffi-bindings", "development-tools::ffi"] +license = "BSD-3-Clause" +name = "bindgen-cli" +readme = "../README.md" +repository = "https://github.com/rust-lang/rust-bindgen" +documentation = "https://docs.rs/bindgen" +homepage = "https://rust-lang.github.io/rust-bindgen/" +version = "0.72.0" +rust-version.workspace = true +edition.workspace = true + +[[bin]] +path = "main.rs" +name = "bindgen" + +[dependencies] +bindgen = { workspace = true, features = ["__cli", "experimental", "prettyplease"] } +env_logger = { workspace = true, optional = true } +log = { workspace = true, optional = true } +proc-macro2.workspace = true +shlex.workspace = true + +[features] +default = ["logging", "runtime"] +logging = ["bindgen/logging", "dep:env_logger", "dep:log"] +static = ["bindgen/static"] +runtime = ["bindgen/runtime"] +prettyplease = ["bindgen/prettyplease"] + +## The following features are for internal use and they shouldn't be used if +## you're not hacking on bindgen +# Features used for CI testing +__testing_only_extra_assertions = ["bindgen/__testing_only_extra_assertions"] +__testing_only_libclang_9 = ["bindgen/__testing_only_libclang_9"] +__testing_only_libclang_16 = ["bindgen/__testing_only_libclang_16"] + +[package.metadata.release] +release = true + +[package.metadata.dist] +dist = true diff --git a/bindgen-cli/LICENSE b/bindgen-cli/LICENSE new file mode 120000 index 0000000000..ea5b60640b --- /dev/null +++ b/bindgen-cli/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/bindgen-cli/main.rs b/bindgen-cli/main.rs new file mode 100644 index 0000000000..2d8d370ef1 --- /dev/null +++ b/bindgen-cli/main.rs @@ -0,0 +1,74 @@ +use std::env; + +use bindgen::builder_from_flags; + +#[cfg(feature = "logging")] +fn clang_version_check() { + let version = bindgen::clang_version(); + let expected_version = if cfg!(feature = "__testing_only_libclang_16") { + Some((16, 0)) + } else if cfg!(feature = "__testing_only_libclang_9") { + Some((9, 0)) + } else { + None + }; + + log::info!( + "Clang Version: {}, parsed: {:?}", + version.full, + version.parsed + ); + + if expected_version.is_some() { + // assert_eq!(version.parsed, version.parsed); + } +} + +pub fn main() { + #[cfg(feature = "logging")] + env_logger::init(); + + match builder_from_flags(env::args()) { + Ok((builder, output, verbose)) => { + #[cfg(feature = "logging")] + clang_version_check(); + + std::panic::set_hook(Box::new(move |info| { + if verbose { + print_verbose_err(); + } + eprintln!("{info}"); + })); + + let bindings = match builder.generate() { + Ok(bindings) => bindings, + Err(err) => { + eprintln!("Unable to generate bindings: {err}"); + std::process::exit(1) + } + }; + + let _ = std::panic::take_hook(); + + bindings.write(output).expect("Unable to write output"); + } + Err(error) => { + eprintln!("{error}"); + std::process::exit(1); + } + }; +} + +fn print_verbose_err() { + eprintln!("Bindgen unexpectedly panicked"); + eprintln!( + "This may be caused by one of the known-unsupported \ + things (https://rust-lang.github.io/rust-bindgen/cpp.html), \ + please modify the bindgen flags to work around it as \ + described in https://rust-lang.github.io/rust-bindgen/cpp.html" + ); + eprintln!( + "Otherwise, please file an issue at \ + https://github.com/rust-lang/rust-bindgen/issues/new" + ); +} diff --git a/bindgen-integration/.gitattributes b/bindgen-integration/.gitattributes new file mode 100644 index 0000000000..d42187e6fe --- /dev/null +++ b/bindgen-integration/.gitattributes @@ -0,0 +1,4 @@ +# Tell Github Linguist to avoid counting these C and C++ test inputs toward +# statistics. +*.h -linguist-detectable +*.cc -linguist-detectable diff --git a/bindgen-integration/Cargo.toml b/bindgen-integration/Cargo.toml index 126cb363bd..5c8c89d528 100644 --- a/bindgen-integration/Cargo.toml +++ b/bindgen-integration/Cargo.toml @@ -1,3 +1,5 @@ +lints.workspace = true + [package] name = "bindgen-integration" description = "A package to test various bindgen features" @@ -5,13 +7,17 @@ version = "0.1.0" authors = ["Emilio Cobos Álvarez "] publish = false build = "build.rs" +rust-version.workspace = true +edition.workspace = true [build-dependencies] -bindgen = { path = ".." } -gcc = "0.3" +bindgen = { workspace = true, default-features = true, features = ["experimental"] } +cc.workspace = true [features] -testing_only_libclang_5 = ["bindgen/testing_only_libclang_5"] -testing_only_libclang_4 = ["bindgen/testing_only_libclang_4"] -testing_only_libclang_3_9 = ["bindgen/testing_only_libclang_3_9"] -testing_only_libclang_3_8 = ["bindgen/testing_only_libclang_3_8"] +static = ["bindgen/static"] +runtime = ["bindgen/runtime"] + +__testing_only_extra_assertions = ["bindgen/__testing_only_extra_assertions"] +__testing_only_libclang_9 = ["bindgen/__testing_only_libclang_9"] +__testing_only_libclang_16 = ["bindgen/__testing_only_libclang_16"] diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index ed5b928150..1b7c2b3b82 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -1,16 +1,20 @@ extern crate bindgen; -extern crate gcc; +use bindgen::callbacks::{ + DeriveInfo, IntKind, ItemInfo, MacroParsingBehavior, ParseCallbacks, Token, + TokenKind, +}; +use bindgen::{Builder, EnumVariation, Formatter}; use std::collections::HashSet; use std::env; use std::path::PathBuf; -use std::sync::{Arc, RwLock}; -use bindgen::Builder; -use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; +use std::sync::{Arc, Mutex, RwLock}; #[derive(Debug)] struct MacroCallback { macros: Arc>>, + seen_hellos: Mutex, + seen_funcs: Mutex, } impl ParseCallbacks for MacroCallback { @@ -18,36 +22,348 @@ impl ParseCallbacks for MacroCallback { self.macros.write().unwrap().insert(name.into()); if name == "MY_ANNOYING_MACRO" { - return MacroParsingBehavior::Ignore + return MacroParsingBehavior::Ignore; } MacroParsingBehavior::Default } + + fn int_macro(&self, name: &str, _value: i64) -> Option { + match name { + "TESTMACRO_CUSTOMINTKIND_PATH" => Some(IntKind::Custom { + name: "crate::MacroInteger", + is_signed: true, + }), + + _ => None, + } + } + + fn str_macro(&self, name: &str, value: &[u8]) { + match name { + "TESTMACRO_STRING_EXPR" => { + assert_eq!(value, b"string"); + *self.seen_hellos.lock().unwrap() += 1; + } + "TESTMACRO_STRING_EXPANDED" | + "TESTMACRO_STRING" | + "TESTMACRO_INTEGER" => { + // The integer test macro is, actually, not expected to show up here at all -- but + // should produce an error if it does. + assert_eq!( + value, b"Hello Preprocessor!", + "str_macro handle received unexpected value" + ); + *self.seen_hellos.lock().unwrap() += 1; + } + _ => {} + } + } + + fn func_macro(&self, name: &str, value: &[&[u8]]) { + match name { + "TESTMACRO_NONFUNCTIONAL" => { + panic!("func_macro was called for a non-functional macro"); + } + "TESTMACRO_FUNCTIONAL_NONEMPTY(TESTMACRO_INTEGER)" => { + // Spaces are inserted into the right-hand side of a functional + // macro during reconstruction from the tokenization. This might + // change in the future, but it is safe by the definition of a + // token in C, whereas leaving the spaces out could change + // tokenization. + assert_eq!(value, &[b"-" as &[u8], b"TESTMACRO_INTEGER"]); + *self.seen_funcs.lock().unwrap() += 1; + } + "TESTMACRO_FUNCTIONAL_EMPTY(TESTMACRO_INTEGER)" => { + assert_eq!(value, &[] as &[&[u8]]); + *self.seen_funcs.lock().unwrap() += 1; + } + "TESTMACRO_FUNCTIONAL_TOKENIZED(a,b,c,d,e)" => { + assert_eq!( + value, + &[b"a" as &[u8], b"/", b"b", b"c", b"d", b"##", b"e"] + ); + *self.seen_funcs.lock().unwrap() += 1; + } + "TESTMACRO_FUNCTIONAL_SPLIT(a,b)" => { + assert_eq!(value, &[b"b", b",", b"a"]); + *self.seen_funcs.lock().unwrap() += 1; + } + "TESTMACRO_STRING_FUNC_NON_UTF8(x)" => { + assert_eq!( + value, + &[b"(" as &[u8], b"x", b"\"\xff\xff\"", b")"] + ); + *self.seen_funcs.lock().unwrap() += 1; + } + _ => { + // The system might provide lots of functional macros. + // Ensure we did not miss handling one that we meant to handle. + assert!(!name.starts_with("TESTMACRO_"), "name = {name}"); + } + } + } + + fn item_name(&self, item_info: ItemInfo) -> Option { + if item_info.name.starts_with("my_prefixed_") { + Some( + item_info + .name + .trim_start_matches("my_prefixed_") + .to_string(), + ) + } else if item_info.name.starts_with("MY_PREFIXED_") { + Some( + item_info + .name + .trim_start_matches("MY_PREFIXED_") + .to_string(), + ) + } else { + None + } + } + + // Test the "custom derives" capability by adding `PartialEq` to the `Test` struct. + fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec { + if info.name == "Test" { + vec!["PartialEq".into()] + } else if info.name == "MyOrderedEnum" { + vec!["std::cmp::PartialOrd".into()] + } else if info.name == "TestDeriveOnAlias" { + vec!["std::cmp::PartialEq".into(), "std::cmp::PartialOrd".into()] + } else { + vec![] + } + } + + // Test the "custom attributes" capability. + fn add_attributes( + &self, + info: &bindgen::callbacks::AttributeInfo<'_>, + ) -> Vec { + if info.name == "Test" { + vec!["#[cfg_attr(test, derive(PartialOrd))]".into()] + } else { + vec![] + } + } + + fn modify_macro(&self, _name: &str, tokens: &mut Vec) { + // Handle macros dealing with bit positions of the format HI:LO + if tokens.len() == 4 && tokens[2].kind == TokenKind::Punctuation { + if let Ok(colon) = std::str::from_utf8(&tokens[2].raw) { + if colon != ":" { + return; + } + let high = match std::str::from_utf8(&tokens[1].raw) { + Ok(s) => { + if let Ok(val) = s.parse::() { + val + } else { + return; + } + } + Err(_) => { + return; + } + }; + + let low = match std::str::from_utf8(&tokens[3].raw) { + Ok(s) => { + if let Ok(val) = s.parse::() { + val + } else { + return; + } + } + Err(_) => { + return; + } + }; + let value: u32 = ((high as u32) << 16) | low as u32; + tokens[1] = Token::from(( + TokenKind::Literal, + value.to_string().as_bytes(), + )); + tokens.truncate(2); + } + } + } } -fn main() { - gcc::Build::new() +impl Drop for MacroCallback { + fn drop(&mut self) { + assert_eq!( + *self.seen_hellos.lock().unwrap(), + 3, + "str_macro handle was not called once for all relevant macros" + ); + assert_eq!( + *self.seen_funcs.lock().unwrap(), + 5, + "func_macro handle was not called once for all relevant macros" + ); + } +} + +#[derive(Debug)] +struct WrappedVaListCallback; + +impl ParseCallbacks for WrappedVaListCallback { + fn wrap_as_variadic_fn(&self, name: &str) -> Option { + Some(name.to_owned() + "_wrapped") + } +} + +fn setup_macro_test() { + cc::Build::new() .cpp(true) .file("cpp/Test.cc") + .include("include") .compile("libtest.a"); let macros = Arc::new(RwLock::new(HashSet::new())); + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let out_rust_file = out_path.join("test.rs"); + let out_rust_file_relative = out_rust_file + .strip_prefix(env::current_dir().unwrap().parent().unwrap()) + .unwrap(); + let out_dep_file = out_path.join("test.d"); + let bindings = Builder::default() - .rustfmt_bindings(false) + .formatter(Formatter::None) .enable_cxx_namespaces() - .rustified_enum(".*") + .default_enum_style(EnumVariation::Rust { + non_exhaustive: false, + }) .raw_line("pub use self::root::*;") + .raw_line("extern { fn my_prefixed_function_to_remove(i: i32); }") + .module_raw_line("root::testing", "pub type Bar = i32;") .header("cpp/Test.h") - .clang_args(&["-x", "c++", "-std=c++11"]) - .parse_callbacks(Box::new(MacroCallback {macros: macros.clone()})) + .clang_args(&["-x", "c++", "-std=c++11", "-I", "include"]) + .parse_callbacks(Box::new(MacroCallback { + macros: macros.clone(), + seen_hellos: Mutex::new(0), + seen_funcs: Mutex::new(0), + })) + .blocklist_function("my_prefixed_function_to_remove") + .constified_enum("my_prefixed_enum_to_be_constified") + .opaque_type("my_prefixed_templated_foo") + .new_type_alias("MyInt") + .new_type_alias("MyBool") + .new_type_alias("MyFloat") + .new_type_alias("MyChar") + .new_type_alias("TestDeriveOnAlias") + .depfile(out_rust_file_relative.display().to_string(), &out_dep_file) .generate() .expect("Unable to generate bindings"); assert!(macros.read().unwrap().contains("TESTMACRO")); + bindings + .write_to_file(&out_rust_file) + .expect("Couldn't write bindings!"); + let observed_deps = + std::fs::read_to_string(out_dep_file).expect("Couldn't read depfile!"); + let expected_deps = format!( + "{}: cpp/Test.h include/stub.h", + out_rust_file_relative.display() + ); + assert_eq!( + observed_deps, expected_deps, + "including stub via include dir must produce correct dep path", + ); +} + +fn setup_wrap_static_fns_test() { + // GH-1090: https://github.com/rust-lang/rust-bindgen/issues/1090 + // set output directory under /target so it is easy to clean generated files let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let out_rust_file = out_path.join("extern.rs"); + + let input_header_dir = PathBuf::from("../bindgen-tests/tests/headers/") + .canonicalize() + .expect("Cannot canonicalize libdir path"); + let input_header_file_path = input_header_dir.join("wrap-static-fns.h"); + let input_header_file_path_str = input_header_file_path + .to_str() + .expect("Path could not be converted to a str"); + + // generate external bindings with the external .c and .h files + #[allow(unused_mut)] + let mut builder = Builder::default() + .header(input_header_file_path_str) + .parse_callbacks(Box::new( + bindgen::CargoCallbacks::new().rerun_on_header_files(true), + )) + .parse_callbacks(Box::new(WrappedVaListCallback)) + .wrap_static_fns(true) + .wrap_static_fns_path( + out_path.join("wrap_static_fns").display().to_string(), + ) + .clang_arg("-DUSE_VA_HEADER"); + + // aarch64-linux has a bug, remove again when it is solved: + // https://github.com/rust-lang/rust-bindgen/issues/3234 + #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + { + builder = builder.clang_arg("-DDISABLE_VA"); + } + + let bindings = builder.generate().expect("Unable to generate bindings"); + + println!("cargo:rustc-link-lib=static=wrap_static_fns"); // tell cargo to link libextern + println!("bindings generated: {bindings}"); + + let obj_path = out_path.join("wrap_static_fns.o"); + let lib_path = out_path.join("libwrap_static_fns.a"); + + // build the external files to check if they work + let mut command = std::process::Command::new("clang"); + command + .arg("-c") + .arg("-o") + .arg(&obj_path) + .arg(out_path.join("wrap_static_fns.c")) + .arg("-DUSE_VA_HEADER"); + + // aarch64-linux has a bug, remove again when it is solved: + // https://github.com/rust-lang/rust-bindgen/issues/3234 + #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + { + command.arg("-DDISABLE_VA"); + } + + let clang_output = command.output().expect("`clang` command error"); + if !clang_output.status.success() { + panic!( + "Could not compile object file:\n{}", + String::from_utf8_lossy(&clang_output.stderr) + ); + } + + let ar_output = std::process::Command::new("ar") + .arg("rcs") + .arg(lib_path) + .arg(obj_path) + .output() + .expect("`ar` command error"); + + if !ar_output.status.success() { + panic!( + "Could not emit library file:\n{}", + String::from_utf8_lossy(&ar_output.stderr) + ); + } + bindings - .write_to_file(out_path.join("test.rs")) - .expect("Couldn't write bindings!"); + .write_to_file(out_rust_file) + .expect("Could not write bindings to the Rust file"); +} + +fn main() { + setup_macro_test(); + setup_wrap_static_fns_test(); } diff --git a/bindgen-integration/cpp/Test.cc b/bindgen-integration/cpp/Test.cc index 80ae0239e5..71a0a4b9c7 100644 --- a/bindgen-integration/cpp/Test.cc +++ b/bindgen-integration/cpp/Test.cc @@ -131,3 +131,16 @@ Seventh::assert(bool first, }; } // namespace bitfields + +int my_prefixed_function_name() { + return 4; +} + +Coord coord(double x, double y, double z, double t) { + Coord res; + res.v[0] = x; + res.v[1] = y; + res.v[2] = z; + res.v[3] = t; + return res; +} diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index e09c9ee72a..25858b2790 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -1,7 +1,29 @@ +#include "stub.h" // this bad path is made valid by a `-I include` clang arg + #pragma once #define TESTMACRO +#define TESTMACRO_INTEGER 42 +#define TESTMACRO_STRING "Hello Preprocessor!" +#define TESTMACRO_STRING_EXPANDED TESTMACRO_STRING +#define TESTMACRO_CUSTOMINTKIND_PATH 123 + +// The following two macros are parsed the same by cexpr, but are semantically +// different. +#define TESTMACRO_NONFUNCTIONAL (TESTMACRO_INTEGER) +#define TESTMACRO_FUNCTIONAL_EMPTY(TESTMACRO_INTEGER) +#define TESTMACRO_FUNCTIONAL_NONEMPTY(TESTMACRO_INTEGER)-TESTMACRO_INTEGER +#define TESTMACRO_FUNCTIONAL_TOKENIZED( a, b ,c,d,e ) a/b c d ## e +#define TESTMACRO_FUNCTIONAL_SPLIT( a, \ + b) b,\ + a +//#define TESTMACRO_INVALID("string") // A conforming preprocessor rejects this +#define TESTMACRO_STRING_EXPR ("string") +#define TESTMACRO_STRING_FUNC_NON_UTF8(x) (x "��") /* invalid UTF-8 on purpose */ + +#define TESTMACRO_COLON_VALUE 1:2 + enum { MY_ANNOYING_MACRO = #define MY_ANNOYING_MACRO 1 @@ -172,3 +194,68 @@ struct AutoRestoreBool { AutoRestoreBool(bool*); ~AutoRestoreBool(); }; + +struct WithWChar { + wchar_t foo[30]; +}; + +// The names of the following items are unprefixed by the parse callbacks. +const int MY_PREFIXED_CONST_VALUE = 3; + +int my_prefixed_function_name(); + +struct my_prefixed_bar { + int foo; +}; + +struct my_prefixed_foo { + my_prefixed_bar member; +}; + +enum my_prefixed_enum_to_be_constified { + ONE = 1, + TWO, + THREE, +}; + +struct my_prefixed_baz { + char foo[30]; +}; + +template +struct my_prefixed_templated_foo { + T member; +}; + +my_prefixed_templated_foo TEMPLATED_CONST_VALUE; + +void my_prefixed_function_to_remove(); + +typedef union { + double v[4]; +} Coord; + +Coord coord(double x, double y, double z, double t); + +// Used to test custom derives on enum. See `test_custom_derive`. +enum MyOrderedEnum { + MICRON, + METER, + LIGHTYEAR, +}; + +// Used to test custom derives on new-type alias. See `test_custom_derive`. +typedef int TestDeriveOnAlias; + +// Used to test new-type alias constants. See `test_new_type_alias_const`. +typedef int MyInt; +const MyInt MY_INT = 5; + +typedef bool MyBool; +const MyBool MY_BOOL = true; + +typedef float MyFloat; +const MyFloat MY_FLOAT = 1.23f; + +typedef char MyChar; +const MyChar MY_CHAR = 'a'; diff --git a/tests/expectations/src/lib.rs b/bindgen-integration/include/stub.h similarity index 100% rename from tests/expectations/src/lib.rs rename to bindgen-integration/include/stub.h diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 176da3bb20..8c31121b4b 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -4,14 +4,22 @@ mod bindings { include!(concat!(env!("OUT_DIR"), "/test.rs")); } +mod extern_bindings { + include!(concat!(env!("OUT_DIR"), "/extern.rs")); +} + use std::ffi::CStr; -use std::os::raw::c_int; use std::mem; +use std::os::raw::c_int; + +use bindings::testing::Bar; // This type is generated from module_raw_line. + +type MacroInteger = isize; #[test] fn test_static_array() { let mut test = unsafe { bindings::Test_COUNTDOWN.as_ptr() }; - let expected = unsafe { bindings::Test_countdown()}; + let expected = unsafe { bindings::Test_countdown() }; let also_expected = unsafe { bindings::Test_COUNTDOWN_PTR }; assert!(!test.is_null()); assert_eq!(also_expected, expected); @@ -53,63 +61,41 @@ fn test_overload() { #[test] fn test_bitfields_first() { - let mut first: bindings::bitfields::First = unsafe { - mem::zeroed() - }; - assert!(unsafe { - first.assert(0, 0, 0) - }); + let mut first: bindings::bitfields::First = unsafe { mem::zeroed() }; + assert!(unsafe { first.assert(0, 0, 0) }); first.set_three_bits_byte_one(2); first.set_six_bits_byte_two(42); first.set_two_bits_byte_two(1); - assert!(unsafe { - first.assert(2, 42, 1) - }); + assert!(unsafe { first.assert(2, 42, 1) }); } #[test] fn test_bitfields_second() { - let mut second: bindings::bitfields::Second = unsafe { - mem::zeroed() - }; - assert!(unsafe { - second.assert(0, false) - }); + let mut second: bindings::bitfields::Second = unsafe { mem::zeroed() }; + assert!(unsafe { second.assert(0, false) }); second.set_thirty_one_bits(1337); second.set_one_bit(true); - assert!(unsafe { - second.assert(1337, true) - }); + assert!(unsafe { second.assert(1337, true) }); } #[test] fn test_bitfields_third() { - let mut third: bindings::bitfields::Third = unsafe { - mem::zeroed() - }; + let mut third: bindings::bitfields::Third = unsafe { mem::zeroed() }; assert!(unsafe { - third.assert(0, - false, - bindings::bitfields::ItemKind::ITEM_KIND_UNO) + third.assert(0, false, bindings::bitfields::ItemKind::ITEM_KIND_UNO) }); third.set_flags(12345); third.set_is_whatever(true); third.set_kind(bindings::bitfields::ItemKind::ITEM_KIND_TRES); assert!(unsafe { - third.assert(12345, - true, - bindings::bitfields::ItemKind::ITEM_KIND_TRES) + third.assert(12345, true, bindings::bitfields::ItemKind::ITEM_KIND_TRES) }); } #[test] fn test_bitfields_fourth() { - let mut fourth: bindings::bitfields::Fourth = unsafe { - mem::zeroed() - }; - assert!(unsafe { - fourth.assert(bindings::bitfields::MyEnum::ONE, 0) - }); + let mut fourth: bindings::bitfields::Fourth = unsafe { mem::zeroed() }; + assert!(unsafe { fourth.assert(bindings::bitfields::MyEnum::ONE, 0) }); fourth.set_tag(bindings::bitfields::MyEnum::THREE); fourth.set_ptr(0xdeadbeef); @@ -120,32 +106,22 @@ fn test_bitfields_fourth() { #[test] fn test_bitfields_date2() { - let mut date: bindings::bitfields::Date2 = unsafe { - mem::zeroed() - }; - assert!(unsafe { - date.assert(0, 0, 0, 0, 0) - }); + let mut date: bindings::bitfields::Date2 = unsafe { mem::zeroed() }; + assert!(unsafe { date.assert(0, 0, 0, 0, 0) }); date.set_nWeekDay(6); // saturdays are the best date.set_nMonthDay(20); date.set_nMonth(11); date.set_nYear(95); date.set_byte(255); - assert!(unsafe { - date.assert(6, 20, 11, 95, 255) - }); + assert!(unsafe { date.assert(6, 20, 11, 95, 255) }); } #[test] fn test_bitfields_fifth() { - let mut date: bindings::bitfields::Fifth = unsafe { - mem::zeroed() - }; + let mut date: bindings::bitfields::Fifth = unsafe { mem::zeroed() }; - assert!(unsafe { - date.assert(0, 0, 0, 0, 0) - }); + assert!(unsafe { date.assert(0, 0, 0, 0, 0) }); date.byte = 255; // Set this first, to ensure we don't override it. @@ -154,40 +130,28 @@ fn test_bitfields_fifth() { date.set_nMonth(11); date.set_nYear(95); - assert!(unsafe { - date.assert(6, 20, 11, 95, 255) - }); + assert!(unsafe { date.assert(6, 20, 11, 95, 255) }); } #[test] fn test_bitfields_sixth() { - let mut date: bindings::bitfields::Sixth = unsafe { - mem::zeroed() - }; + let mut date: bindings::bitfields::Sixth = unsafe { mem::zeroed() }; - assert!(unsafe { - date.assert(0, 0, 0, 0) - }); + assert!(unsafe { date.assert(0, 0, 0, 0) }); date.byte = 255; date.set_nWeekDay(6); // saturdays are the best date.set_nMonthDay(20); date.set_nMonth(11); - assert!(unsafe { - date.assert(255, 6, 11, 20) - }); + assert!(unsafe { date.assert(255, 6, 11, 20) }); } #[test] fn test_bitfields_seventh() { - let mut large: bindings::bitfields::Seventh = unsafe { - mem::zeroed() - }; + let mut large: bindings::bitfields::Seventh = unsafe { mem::zeroed() }; - assert!(unsafe { - large.assert(false, 0, 0, 0, 0, false, 0) - }); + assert!(unsafe { large.assert(false, 0, 0, 0, 0, false, 0) }); large.set_first_one_bit(true); large.set_second_thirty_bits(375028802); @@ -214,32 +178,26 @@ fn test_bitfields_seventh() { fn test_bitfield_constructors() { use std::mem; let mut first = bindings::bitfields::First { - _bitfield_1: bindings::bitfields::First::new_bitfield_1(1, 2, 3) + _bitfield_1: bindings::bitfields::First::new_bitfield_1(1, 2, 3), }; - assert!(unsafe { - first.assert(1, 2, 3) - }); + assert!(unsafe { first.assert(1, 2, 3) }); let mut second = bindings::bitfields::Second { + _bindgen_align: [], _bitfield_1: bindings::bitfields::Second::new_bitfield_1(1337, true), - __bindgen_align: [], }; - assert!(unsafe { - second.assert(1337, true) - }); + assert!(unsafe { second.assert(1337, true) }); let mut third = bindings::bitfields::Third { + _bindgen_align: [], _bitfield_1: bindings::bitfields::Third::new_bitfield_1( 42, false, - bindings::bitfields::ItemKind::ITEM_KIND_TRES + bindings::bitfields::ItemKind::ITEM_KIND_TRES, ), - __bindgen_align: [], }; assert!(unsafe { - third.assert(42, - false, - bindings::bitfields::ItemKind::ITEM_KIND_TRES) + third.assert(42, false, bindings::bitfields::ItemKind::ITEM_KIND_TRES) }); } @@ -263,7 +221,9 @@ fn test_destructors() { impl Drop for bindings::InheritsFromVirtualDestructor { fn drop(&mut self) { - unsafe { bindings::InheritsFromVirtualDestructor_InheritsFromVirtualDestructor_destructor(self) } + unsafe { + bindings::InheritsFromVirtualDestructor_InheritsFromVirtualDestructor_destructor(self) + } } } @@ -279,3 +239,127 @@ fn test_virtual_dtor() { assert_eq!(bindings::VirtualDestructor_sDestructorCount, 1); } } + +#[test] +fn test_item_rename() { + assert_eq!(bindings::CONST_VALUE, 3); + assert_eq!(unsafe { bindings::function_name() }, 4); + + let _foo = bindings::foo { + member: bindings::bar { foo: 2 }, + }; +} + +#[test] +fn test_matching_with_rename() { + assert_eq!(bindings::enum_to_be_constified_THREE, 3); + assert_eq!(unsafe { bindings::TEMPLATED_CONST_VALUE.0.len() }, 30); +} + +#[test] +fn test_macro_customintkind_path() { + let v: &dyn std::any::Any = &bindings::TESTMACRO_CUSTOMINTKIND_PATH; + assert!(v.is::()) +} + +#[test] +fn test_homogeneous_aggregate_float_union() { + unsafe { + let coord = &bindings::coord(1., 2., 3., 4.); + assert_eq!([1., 2., 3., 4.], coord.v) + } +} + +#[test] +fn test_custom_derive() { + // The `add_derives` callback should have added `#[derive(PartialEq)]` + // to the `Test` struct. If it didn't, this will fail to compile. + let test1 = unsafe { bindings::Test::new(5) }; + let test2 = unsafe { bindings::Test::new(6) }; + assert_ne!(test1, test2); + + // The `add_derives` callback should have added `#[derive(PartialOrd)]` + // to the `MyOrderedEnum` enum. If it didn't, this will fail to compile. + + let micron = unsafe { bindings::MyOrderedEnum::MICRON }; + let meter = unsafe { bindings::MyOrderedEnum::METER }; + let lightyear = unsafe { bindings::MyOrderedEnum::LIGHTYEAR }; + + assert!(meter < lightyear); + assert!(meter > micron); + + // The `add_derives` callback should have added `#[derive(PartialEq, PartialOrd)]` + // to the `TestDeriveOnAlias` new-type alias. If it didn't, this will fail to compile. + let test1 = unsafe { bindings::TestDeriveOnAlias(5) }; + let test2 = unsafe { bindings::TestDeriveOnAlias(6) }; + assert!(test1 < test2); + assert!(!(test1 > test2)); +} + +#[test] +fn test_custom_attributes() { + // The `add_attributes` callback should have added `#[cfg_attr(test, derive(PartialOrd))])` + // to the `Test` struct. If it didn't, this will fail to compile. + let test1 = unsafe { bindings::Test::new(5) }; + let test2 = unsafe { bindings::Test::new(6) }; + assert!(test1 < test2); +} + +#[test] +fn test_wrap_static_fns() { + // GH-1090: https://github.com/rust-lang/rust-bindgen/issues/1090 + unsafe { + let f = extern_bindings::foo(); + assert_eq!(11, f); + + let b = extern_bindings::bar(); + assert_eq!(1, b); + + let t = extern_bindings::takes_ptr(&mut 1); + assert_eq!(2, t); + + extern "C" fn function(x: i32) -> i32 { + x + 1 + } + + let tp = extern_bindings::takes_fn_ptr(Some(function)); + assert_eq!(2, tp); + + let tf = extern_bindings::takes_fn(Some(function)); + assert_eq!(3, tf); + + let ta = extern_bindings::takes_alias(Some(function)); + assert_eq!(4, ta); + + let tq = + extern_bindings::takes_qualified(&(&5 as *const _) as *const _); + assert_eq!(5, tq); + + // aarch64-linux has a bug, enable again when it is solved: + // https://github.com/rust-lang/rust-bindgen/issues/3234 + #[cfg(not(all(target_arch = "aarch64", target_os = "linux")))] + { + let wv1 = extern_bindings::wrap_as_variadic_fn1_wrapped(0); + assert_eq!(0, wv1); + + let wv1 = extern_bindings::wrap_as_variadic_fn1_wrapped(2, 5, 3); + assert_eq!(8, wv1); + + extern_bindings::wrap_as_variadic_fn2_wrapped(1, 2); + } + } +} + +#[test] +fn test_colon_define() { + let gold: u32 = (1u32 << 16) | 2; + assert_eq!(gold, bindings::TESTMACRO_COLON_VALUE); +} + +#[test] +fn test_new_type_alias_const() { + assert_eq!(bindings::MY_INT.0, 5); + assert_eq!(bindings::MY_BOOL.0, true); + assert_eq!(bindings::MY_FLOAT.0, 1.23f32); + assert_eq!(bindings::MY_CHAR.0, b'a' as std::ffi::c_char); +} diff --git a/bindgen-tests/Cargo.toml b/bindgen-tests/Cargo.toml new file mode 100644 index 0000000000..77a28ca3cb --- /dev/null +++ b/bindgen-tests/Cargo.toml @@ -0,0 +1,28 @@ +lints.workspace = true + +[package] +name = "bindgen-tests" +version = "0.1.0" +publish = false +rust-version.workspace = true +edition.workspace = true + +[dev-dependencies] +bindgen = { workspace = true, default-features = true, features = ["__cli", "experimental"] } +owo-colors.workspace = true +prettyplease = { workspace = true, features = ["verbatim"] } +proc-macro2.workspace = true +regex.workspace = true +shlex.workspace = true +similar = { workspace = true, features = ["inline"] } +syn.workspace = true +tempfile.workspace = true + +[features] +logging = ["bindgen/logging"] +static = ["bindgen/static"] +runtime = ["bindgen/runtime"] + +__testing_only_extra_assertions = ["bindgen/__testing_only_extra_assertions"] +__testing_only_libclang_9 = ["bindgen/__testing_only_libclang_9"] +__testing_only_libclang_16 = ["bindgen/__testing_only_libclang_16"] diff --git a/bindgen-tests/build.rs b/bindgen-tests/build.rs new file mode 100644 index 0000000000..cf929b4b65 --- /dev/null +++ b/bindgen-tests/build.rs @@ -0,0 +1,44 @@ +use std::char; +use std::env; +use std::fs::{self, File}; +use std::io::Write; +use std::path::{Path, PathBuf}; + +pub fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let mut dst = File::create(Path::new(&out_dir).join("tests.rs")).unwrap(); + + let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let headers_dir = manifest_dir.join("tests").join("headers"); + + let Ok(headers) = fs::read_dir(headers_dir) else { + // We may not have headers directory after packaging. + return; + }; + + let entries = + headers.map(|result| result.expect("Couldn't read header file")); + + println!("cargo:rerun-if-changed=tests/headers"); + + for entry in entries { + // TODO: file_is_cpp() in bindgen/lib.rs checks for hpp,hxx,hh, and h++ - should this be consistent? + if entry.path().extension().is_some_and(|ext| { + ext.eq_ignore_ascii_case("h") || ext.eq_ignore_ascii_case("hpp") + }) { + let func = entry + .file_name() + .to_str() + .unwrap() + .replace(|c| !char::is_alphanumeric(c), "_") + .replace("__", "_") + .to_lowercase(); + // We actually want the quotes and escape + #[allow(clippy::unnecessary_debug_formatting)] + writeln!(dst, "test_header!(header_{func}, {:?});", entry.path()) + .unwrap(); + } + } + + dst.flush().unwrap(); +} diff --git a/tests/expectations/struct_with_anon_struct_array_float.rs b/bindgen-tests/src/lib.rs similarity index 100% rename from tests/expectations/struct_with_anon_struct_array_float.rs rename to bindgen-tests/src/lib.rs diff --git a/bindgen-tests/tests/.gitattributes b/bindgen-tests/tests/.gitattributes new file mode 100644 index 0000000000..96122eb1da --- /dev/null +++ b/bindgen-tests/tests/.gitattributes @@ -0,0 +1,4 @@ +# Tell Github Linguist to avoid counting these C and C++ test inputs toward +# statistics. +*.h -linguist-detectable +*.hpp -linguist-detectable diff --git a/bindgen-tests/tests/expectations/Cargo.toml b/bindgen-tests/tests/expectations/Cargo.toml new file mode 100644 index 0000000000..975fd16678 --- /dev/null +++ b/bindgen-tests/tests/expectations/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "tests_expectations" +description = "bindgen results when ran on ../headers/*" +version = "0.0.0" +authors = [ + "Jyun-Yan You ", + "Emilio Cobos Álvarez ", + "The Servo project developers", +] +publish = false +rust-version.workspace = true +edition.workspace = true + +[dependencies] +block.workspace = true +libloading.workspace = true +objc.workspace = true + +# Both of these sections need to be copied here from the workspace because +# Cargo currently does not allow overriding workspace settings in a member +[lints.rust] +### FIXME: these might need to be fixed, +### esp the calling convention, because it is a hard error now +# deprecated = "allow" +# invalid-value = "allow" +# unsupported_calling_conventions = "allow" +# +# Different from the workspace +dead_code = "allow" +non-snake-case = "allow" +non_camel_case_types = "allow" +non_upper_case_globals = "allow" +unexpected-cfgs = "allow" +unused_qualifications = "allow" + +[lints.clippy] +disallowed-names = "allow" +manual-c-str-literals = "allow" +missing-safety-doc = "allow" +op-ref = "allow" +ptr-offset-with-cast = "allow" +semicolon_if_nothing_returned = "allow" +too-many-arguments = "allow" +transmute-int-to-bool = "allow" +unnecessary-cast = "allow" +useless-transmute = "allow" diff --git a/bindgen-tests/tests/expectations/build.rs b/bindgen-tests/tests/expectations/build.rs new file mode 100644 index 0000000000..f4ded7e12d --- /dev/null +++ b/bindgen-tests/tests/expectations/build.rs @@ -0,0 +1,61 @@ +//! Generate a module with a custom `#[path=...]` for each of the files in our +//! libclang version-specific test expectations so that they get their layout +//! tests run. We need to do this because cargo doesn't automatically detect +//! tests subdirectories. + +use std::env; +use std::fs; +use std::io::Write; +use std::path::Path; + +const LIBCLANG_VERSION_DIRS: &[&str] = &["libclang-9"]; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + let mut test_string = String::new(); + + for dir in LIBCLANG_VERSION_DIRS { + let dir = Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()) + .join("tests") + .join(dir); + + println!("cargo:rerun-if-changed={}", dir.display()); + + for entry in fs::read_dir(dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let path = path.canonicalize().unwrap_or(path); + if path.extension().map(|e| e.to_string_lossy()) != + Some("rs".into()) + { + continue; + } + + println!("cargo:rerun-if-changed={}", path.display()); + + let module_name: String = path + .display() + .to_string() + .chars() + .map(|c| match c { + 'a'..='z' | 'A'..='Z' | '0'..='9' => c, + _ => '_', + }) + .collect(); + + test_string.push_str(&format!( + r###" +#[path = "{}"] +mod {module_name}; +"###, + path.display().to_string().replace('\\', "\\\\"), + )); + } + } + + let out_path = Path::new(&env::var_os("OUT_DIR").unwrap()) + .join("libclang_version_specific_generated_tests.rs"); + let mut test_file = fs::File::create(out_path).unwrap(); + test_file.write_all(test_string.as_bytes()).unwrap(); +} diff --git a/bindgen-tests/tests/expectations/lib.rs b/bindgen-tests/tests/expectations/lib.rs new file mode 100755 index 0000000000..e69de29bb2 diff --git a/bindgen-tests/tests/expectations/rustfmt.toml b/bindgen-tests/tests/expectations/rustfmt.toml new file mode 100644 index 0000000000..85a7173599 --- /dev/null +++ b/bindgen-tests/tests/expectations/rustfmt.toml @@ -0,0 +1,2 @@ +# disable rustfmt for this crate so running `cargo fmt` doesn't affect the expected binding files +disable_all_formatting = true diff --git a/bindgen-tests/tests/expectations/src/lib.rs b/bindgen-tests/tests/expectations/src/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/bindgen-tests/tests/expectations/src/lib.rs @@ -0,0 +1 @@ + diff --git a/bindgen-tests/tests/expectations/struct_with_anon_struct_array_float.rs b/bindgen-tests/tests/expectations/struct_with_anon_struct_array_float.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/bindgen-tests/tests/expectations/struct_with_anon_struct_array_float.rs @@ -0,0 +1 @@ + diff --git a/bindgen-tests/tests/expectations/tests/.gitattributes b/bindgen-tests/tests/expectations/tests/.gitattributes new file mode 100644 index 0000000000..9699dfa001 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/.gitattributes @@ -0,0 +1,2 @@ +# Prevent Github Linguist from counting generated files in statistics. +*.rs linguist-generated diff --git a/bindgen-tests/tests/expectations/tests/16-byte-alignment.rs b/bindgen-tests/tests/expectations/tests/16-byte-alignment.rs new file mode 100644 index 0000000000..c55d0b075b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/16-byte-alignment.rs @@ -0,0 +1,184 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct rte_ipv4_tuple { + pub src_addr: u32, + pub dst_addr: u32, + pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_ipv4_tuple__bindgen_ty_1 { + pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1, + pub sctp_tag: u32, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1 { + pub dport: u16, + pub sport: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1::dport", + ][::std::mem::offset_of!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1, dport) + - 0usize]; + [ + "Offset of field: rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1::sport", + ][::std::mem::offset_of!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1, sport) + - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_ipv4_tuple__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_ipv4_tuple__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ipv4_tuple__bindgen_ty_1::sctp_tag", + ][::std::mem::offset_of!(rte_ipv4_tuple__bindgen_ty_1, sctp_tag) - 0usize]; +}; +impl Default for rte_ipv4_tuple__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ipv4_tuple"][::std::mem::size_of::() - 12usize]; + ["Alignment of rte_ipv4_tuple"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ipv4_tuple::src_addr", + ][::std::mem::offset_of!(rte_ipv4_tuple, src_addr) - 0usize]; + [ + "Offset of field: rte_ipv4_tuple::dst_addr", + ][::std::mem::offset_of!(rte_ipv4_tuple, dst_addr) - 4usize]; +}; +impl Default for rte_ipv4_tuple { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct rte_ipv6_tuple { + pub src_addr: [u8; 16usize], + pub dst_addr: [u8; 16usize], + pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_ipv6_tuple__bindgen_ty_1 { + pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1, + pub sctp_tag: u32, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1 { + pub dport: u16, + pub sport: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1::dport", + ][::std::mem::offset_of!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1, dport) + - 0usize]; + [ + "Offset of field: rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1::sport", + ][::std::mem::offset_of!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1, sport) + - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_ipv6_tuple__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_ipv6_tuple__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ipv6_tuple__bindgen_ty_1::sctp_tag", + ][::std::mem::offset_of!(rte_ipv6_tuple__bindgen_ty_1, sctp_tag) - 0usize]; +}; +impl Default for rte_ipv6_tuple__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ipv6_tuple"][::std::mem::size_of::() - 36usize]; + ["Alignment of rte_ipv6_tuple"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ipv6_tuple::src_addr", + ][::std::mem::offset_of!(rte_ipv6_tuple, src_addr) - 0usize]; + [ + "Offset of field: rte_ipv6_tuple::dst_addr", + ][::std::mem::offset_of!(rte_ipv6_tuple, dst_addr) - 16usize]; +}; +impl Default for rte_ipv6_tuple { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Copy, Clone)] +pub union rte_thash_tuple { + pub v4: rte_ipv4_tuple, + pub v6: rte_ipv6_tuple, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_thash_tuple"][::std::mem::size_of::() - 48usize]; + [ + "Alignment of rte_thash_tuple", + ][::std::mem::align_of::() - 16usize]; + [ + "Offset of field: rte_thash_tuple::v4", + ][::std::mem::offset_of!(rte_thash_tuple, v4) - 0usize]; + [ + "Offset of field: rte_thash_tuple::v6", + ][::std::mem::offset_of!(rte_thash_tuple, v6) - 0usize]; +}; +impl Default for rte_thash_tuple { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/381-decltype-alias.rs b/bindgen-tests/tests/expectations/tests/381-decltype-alias.rs similarity index 83% rename from tests/expectations/tests/381-decltype-alias.rs rename to bindgen-tests/tests/expectations/tests/381-decltype-alias.rs index 7f2bb8787b..ed893c21df 100644 --- a/tests/expectations/tests/381-decltype-alias.rs +++ b/bindgen-tests/tests/expectations/tests/381-decltype-alias.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct std_allocator_traits { diff --git a/bindgen-tests/tests/expectations/tests/abi-override.rs b/bindgen-tests/tests/expectations/tests/abi-override.rs new file mode 100644 index 0000000000..369bfd8d32 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/abi-override.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target = "i686-pc-windows-msvc")] +unsafe extern "fastcall" { + pub fn foo(); +} +unsafe extern "stdcall" { + pub fn bar(); +} +unsafe extern "C" { + pub fn baz(); +} +unsafe extern "system" { + pub fn qux(); +} +pub type boo = ::std::option::Option; +pub type foobar = ::std::option::Option; diff --git a/bindgen-tests/tests/expectations/tests/abi_variadic_function.rs b/bindgen-tests/tests/expectations/tests/abi_variadic_function.rs new file mode 100644 index 0000000000..b57ddafd32 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/abi_variadic_function.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z1bcz"] + pub fn b(arg1: ::std::os::raw::c_char, ...) -> ::std::os::raw::c_char; +} diff --git a/bindgen-tests/tests/expectations/tests/accessors.rs b/bindgen-tests/tests/expectations/tests/accessors.rs new file mode 100644 index 0000000000..586edf2d79 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/accessors.rs @@ -0,0 +1,228 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct SomeAccessors { + pub mNoAccessor: ::std::os::raw::c_int, + ///
+ pub mBothAccessors: ::std::os::raw::c_int, + ///
+ pub mUnsafeAccessors: ::std::os::raw::c_int, + ///
+ pub mImmutableAccessor: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of SomeAccessors"][::std::mem::size_of::() - 16usize]; + ["Alignment of SomeAccessors"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: SomeAccessors::mNoAccessor", + ][::std::mem::offset_of!(SomeAccessors, mNoAccessor) - 0usize]; + [ + "Offset of field: SomeAccessors::mBothAccessors", + ][::std::mem::offset_of!(SomeAccessors, mBothAccessors) - 4usize]; + [ + "Offset of field: SomeAccessors::mUnsafeAccessors", + ][::std::mem::offset_of!(SomeAccessors, mUnsafeAccessors) - 8usize]; + [ + "Offset of field: SomeAccessors::mImmutableAccessor", + ][::std::mem::offset_of!(SomeAccessors, mImmutableAccessor) - 12usize]; +}; +impl SomeAccessors { + #[inline] + pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mBothAccessors + } + #[inline] + pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mBothAccessors + } + #[inline] + pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int { + &self.mUnsafeAccessors + } + #[inline] + pub unsafe fn get_mUnsafeAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mUnsafeAccessors + } + #[inline] + pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { + &self.mImmutableAccessor + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AllAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + pub mAlsoBothAccessors: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllAccessors"][::std::mem::size_of::() - 8usize]; + ["Alignment of AllAccessors"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: AllAccessors::mBothAccessors", + ][::std::mem::offset_of!(AllAccessors, mBothAccessors) - 0usize]; + [ + "Offset of field: AllAccessors::mAlsoBothAccessors", + ][::std::mem::offset_of!(AllAccessors, mAlsoBothAccessors) - 4usize]; +}; +impl AllAccessors { + #[inline] + pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mBothAccessors + } + #[inline] + pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mBothAccessors + } + #[inline] + pub fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mAlsoBothAccessors + } + #[inline] + pub fn get_mAlsoBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mAlsoBothAccessors + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AllUnsafeAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + pub mAlsoBothAccessors: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllUnsafeAccessors"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of AllUnsafeAccessors", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: AllUnsafeAccessors::mBothAccessors", + ][::std::mem::offset_of!(AllUnsafeAccessors, mBothAccessors) - 0usize]; + [ + "Offset of field: AllUnsafeAccessors::mAlsoBothAccessors", + ][::std::mem::offset_of!(AllUnsafeAccessors, mAlsoBothAccessors) - 4usize]; +}; +impl AllUnsafeAccessors { + #[inline] + pub unsafe fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mBothAccessors + } + #[inline] + pub unsafe fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mBothAccessors + } + #[inline] + pub unsafe fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mAlsoBothAccessors + } + #[inline] + pub unsafe fn get_mAlsoBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mAlsoBothAccessors + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ContradictAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + ///
+ pub mNoAccessors: ::std::os::raw::c_int, + ///
+ pub mUnsafeAccessors: ::std::os::raw::c_int, + ///
+ pub mImmutableAccessor: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContradictAccessors", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of ContradictAccessors", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContradictAccessors::mBothAccessors", + ][::std::mem::offset_of!(ContradictAccessors, mBothAccessors) - 0usize]; + [ + "Offset of field: ContradictAccessors::mNoAccessors", + ][::std::mem::offset_of!(ContradictAccessors, mNoAccessors) - 4usize]; + [ + "Offset of field: ContradictAccessors::mUnsafeAccessors", + ][::std::mem::offset_of!(ContradictAccessors, mUnsafeAccessors) - 8usize]; + [ + "Offset of field: ContradictAccessors::mImmutableAccessor", + ][::std::mem::offset_of!(ContradictAccessors, mImmutableAccessor) - 12usize]; +}; +impl ContradictAccessors { + #[inline] + pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { + &self.mBothAccessors + } + #[inline] + pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mBothAccessors + } + #[inline] + pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int { + &self.mUnsafeAccessors + } + #[inline] + pub unsafe fn get_mUnsafeAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mUnsafeAccessors + } + #[inline] + pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { + &self.mImmutableAccessor + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Replaced { + pub mAccessor: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Replaced"][::std::mem::size_of::() - 4usize]; + ["Alignment of Replaced"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Replaced::mAccessor", + ][::std::mem::offset_of!(Replaced, mAccessor) - 0usize]; +}; +impl Replaced { + #[inline] + pub fn get_mAccessor(&self) -> &::std::os::raw::c_int { + &self.mAccessor + } + #[inline] + pub fn get_mAccessor_mut(&mut self) -> &mut ::std::os::raw::c_int { + &mut self.mAccessor + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Wrapper { + pub mReplaced: Replaced, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Wrapper"][::std::mem::size_of::() - 4usize]; + ["Alignment of Wrapper"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Wrapper::mReplaced", + ][::std::mem::offset_of!(Wrapper, mReplaced) - 0usize]; +}; +impl Wrapper { + #[inline] + pub fn get_mReplaced(&self) -> &Replaced { + &self.mReplaced + } + #[inline] + pub fn get_mReplaced_mut(&mut self) -> &mut Replaced { + &mut self.mReplaced + } +} diff --git a/bindgen-tests/tests/expectations/tests/alias_comments.rs b/bindgen-tests/tests/expectations/tests/alias_comments.rs new file mode 100644 index 0000000000..31ff72b2c6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/alias_comments.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// This is Struct +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Struct { + /// This is field + pub field: ::std::os::raw::c_int, +} +/// This is AliasToStruct +pub type AliasToStruct = Struct; +/// This is AliasToInt +pub type AliasToInt = ::std::os::raw::c_int; +/// This is AliasToAliasToInt +pub type AliasToAliasToInt = AliasToInt; diff --git a/bindgen-tests/tests/expectations/tests/allowlist-file.rs b/bindgen-tests/tests/expectations/tests/allowlist-file.rs new file mode 100644 index 0000000000..b1fb170de0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist-file.rs @@ -0,0 +1,92 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const SOME_DEFUN: u32 = 123; +unsafe extern "C" { + #[link_name = "\u{1}_Z12SomeFunctionv"] + pub fn SomeFunction(); +} +unsafe extern "C" { + pub static mut someVar: ::std::os::raw::c_int; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct someClass { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of someClass"][::std::mem::size_of::() - 1usize]; + ["Alignment of someClass"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN9someClass16somePublicMethodEi"] + pub fn someClass_somePublicMethod(this: *mut someClass, foo: ::std::os::raw::c_int); +} +impl someClass { + #[inline] + pub unsafe fn somePublicMethod(&mut self, foo: ::std::os::raw::c_int) { + someClass_somePublicMethod(self, foo) + } +} +unsafe extern "C" { + pub fn ExternFunction(); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3foo18NamespacedFunctionEv"] + pub fn foo_NamespacedFunction(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StructWithAllowlistedDefinition { + pub other: *mut StructWithAllowlistedFwdDecl, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of StructWithAllowlistedDefinition", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of StructWithAllowlistedDefinition", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: StructWithAllowlistedDefinition::other", + ][::std::mem::offset_of!(StructWithAllowlistedDefinition, other) - 0usize]; +}; +impl Default for StructWithAllowlistedDefinition { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct StructWithAllowlistedFwdDecl { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of StructWithAllowlistedFwdDecl", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of StructWithAllowlistedFwdDecl", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: StructWithAllowlistedFwdDecl::b", + ][::std::mem::offset_of!(StructWithAllowlistedFwdDecl, b) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AllowlistMe { + pub foo: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistMe"][::std::mem::size_of::() - 4usize]; + ["Alignment of AllowlistMe"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: AllowlistMe::foo", + ][::std::mem::offset_of!(AllowlistMe, foo) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/allowlist-namespaces-basic.rs b/bindgen-tests/tests/expectations/tests/allowlist-namespaces-basic.rs new file mode 100644 index 0000000000..151d03f4a4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist-namespaces-basic.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod outer { + #[allow(unused_imports)] + use self::super::super::root; + pub mod inner { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Helper { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Helper"][::std::mem::size_of::() - 1usize]; + ["Alignment of Helper"][::std::mem::align_of::() - 1usize]; + }; + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/allowlist-namespaces.rs b/bindgen-tests/tests/expectations/tests/allowlist-namespaces.rs new file mode 100644 index 0000000000..563c97ca1d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist-namespaces.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod outer { + #[allow(unused_imports)] + use self::super::super::root; + pub mod inner { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Helper { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Helper"][::std::mem::size_of::() - 1usize]; + ["Alignment of Helper"][::std::mem::align_of::() - 1usize]; + }; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Test { + pub helper: root::outer::inner::Helper, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Test"][::std::mem::size_of::() - 1usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: Test::helper", + ][::std::mem::offset_of!(Test, helper) - 0usize]; + }; + } +} diff --git a/bindgen-tests/tests/expectations/tests/allowlist_basic.rs b/bindgen-tests/tests/expectations/tests/allowlist_basic.rs new file mode 100644 index 0000000000..a1c6919739 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist_basic.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AllowlistMe { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub foo: ::std::os::raw::c_int, + pub bar: AllowlistMe_Inner, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AllowlistMe_Inner { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub bar: T, +} +impl Default for AllowlistMe_Inner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for AllowlistMe { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/allowlist_fix.rs b/bindgen-tests/tests/expectations/tests/allowlist_fix.rs new file mode 100644 index 0000000000..772772c56c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist_fix.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub enum Test {} +unsafe extern "C" { + pub fn Servo_Test(a: *mut Test); +} diff --git a/bindgen-tests/tests/expectations/tests/allowlist_item.rs b/bindgen-tests/tests/expectations/tests/allowlist_item.rs new file mode 100644 index 0000000000..93eab7e147 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist_item.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FooDefault: u32 = 0; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub field: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::field"][::std::mem::offset_of!(Foo, field) - 0usize]; +}; +unsafe extern "C" { + pub fn FooNew(value: ::std::os::raw::c_int) -> Foo; +} diff --git a/bindgen-tests/tests/expectations/tests/allowlist_vars.rs b/bindgen-tests/tests/expectations/tests/allowlist_vars.rs new file mode 100644 index 0000000000..342d904a73 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist_vars.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const NONE: u32 = 0; +pub const FOO: u32 = 5; +pub const FOOB: i32 = -2; +pub const FOOBAR: i32 = -10; diff --git a/bindgen-tests/tests/expectations/tests/allowlist_warnings.rs b/bindgen-tests/tests/expectations/tests/allowlist_warnings.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlist_warnings.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-hash.rs b/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-hash.rs new file mode 100644 index 0000000000..6c1d13a837 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-hash.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoHash"][::std::mem::size_of::() - 1usize]; + ["Alignment of NoHash"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AllowlistMe { + pub a: NoHash, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistMe"][::std::mem::size_of::() - 1usize]; + ["Alignment of AllowlistMe"][::std::mem::align_of::() - 1usize]; + ["Offset of field: AllowlistMe::a"][::std::mem::offset_of!(AllowlistMe, a) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-partialeq.rs b/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-partialeq.rs new file mode 100644 index 0000000000..b969727dbb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlisted-item-references-no-partialeq.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoPartialEq { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoPartialEq"][::std::mem::size_of::() - 1usize]; + ["Alignment of NoPartialEq"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AllowlistMe { + pub a: NoPartialEq, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistMe"][::std::mem::size_of::() - 1usize]; + ["Alignment of AllowlistMe"][::std::mem::align_of::() - 1usize]; + ["Offset of field: AllowlistMe::a"][::std::mem::offset_of!(AllowlistMe, a) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/allowlisted_item_references_no_copy.rs b/bindgen-tests/tests/expectations/tests/allowlisted_item_references_no_copy.rs new file mode 100644 index 0000000000..8c671b4e84 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/allowlisted_item_references_no_copy.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct NoCopy { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoCopy"][::std::mem::size_of::() - 1usize]; + ["Alignment of NoCopy"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct AllowlistMe { + pub a: NoCopy, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistMe"][::std::mem::size_of::() - 1usize]; + ["Alignment of AllowlistMe"][::std::mem::align_of::() - 1usize]; + ["Offset of field: AllowlistMe::a"][::std::mem::offset_of!(AllowlistMe, a) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/annotation_hide.rs b/bindgen-tests/tests/expectations/tests/annotation_hide.rs new file mode 100644 index 0000000000..e79c88214d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/annotation_hide.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct D { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of D"][::std::mem::size_of::() - 4usize]; + ["Alignment of D"][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NotAnnotated { + pub f: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NotAnnotated"][::std::mem::size_of::() - 4usize]; + ["Alignment of NotAnnotated"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: NotAnnotated::f", + ][::std::mem::offset_of!(NotAnnotated, f) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/anon-fields-prefix.rs b/bindgen-tests/tests/expectations/tests/anon-fields-prefix.rs new file mode 100644 index 0000000000..2b96804c9b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon-fields-prefix.rs @@ -0,0 +1,73 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union color { + pub u1: color__bindgen_ty_1, + pub u2: color__bindgen_ty_2, + pub v3: [::std::os::raw::c_uchar; 3usize], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct color__bindgen_ty_1 { + pub r: ::std::os::raw::c_uchar, + pub g: ::std::os::raw::c_uchar, + pub b: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of color__bindgen_ty_1", + ][::std::mem::size_of::() - 3usize]; + [ + "Alignment of color__bindgen_ty_1", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: color__bindgen_ty_1::r", + ][::std::mem::offset_of!(color__bindgen_ty_1, r) - 0usize]; + [ + "Offset of field: color__bindgen_ty_1::g", + ][::std::mem::offset_of!(color__bindgen_ty_1, g) - 1usize]; + [ + "Offset of field: color__bindgen_ty_1::b", + ][::std::mem::offset_of!(color__bindgen_ty_1, b) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct color__bindgen_ty_2 { + pub y: ::std::os::raw::c_uchar, + pub u: ::std::os::raw::c_uchar, + pub v: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of color__bindgen_ty_2", + ][::std::mem::size_of::() - 3usize]; + [ + "Alignment of color__bindgen_ty_2", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: color__bindgen_ty_2::y", + ][::std::mem::offset_of!(color__bindgen_ty_2, y) - 0usize]; + [ + "Offset of field: color__bindgen_ty_2::u", + ][::std::mem::offset_of!(color__bindgen_ty_2, u) - 1usize]; + [ + "Offset of field: color__bindgen_ty_2::v", + ][::std::mem::offset_of!(color__bindgen_ty_2, v) - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of color"][::std::mem::size_of::() - 3usize]; + ["Alignment of color"][::std::mem::align_of::() - 1usize]; + ["Offset of field: color::v3"][::std::mem::offset_of!(color, v3) - 0usize]; +}; +impl Default for color { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/anon_enum.rs b/bindgen-tests/tests/expectations/tests/anon_enum.rs new file mode 100644 index 0000000000..c3790a2a24 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_enum.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct Test { + pub foo: ::std::os::raw::c_int, + pub bar: f32, +} +pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Test__bindgen_ty_1 { + T_NONE = 0, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 8usize]; + ["Alignment of Test"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Test::foo"][::std::mem::offset_of!(Test, foo) - 0usize]; + ["Offset of field: Test::bar"][::std::mem::offset_of!(Test, bar) - 4usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Baz { + Foo = 0, + Bar = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/anon_enum_allowlist.rs b/bindgen-tests/tests/expectations/tests/anon_enum_allowlist.rs new file mode 100644 index 0000000000..4b172d7aeb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_enum_allowlist.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO; +pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + NODE_FLAG_FOO = 0, + NODE_FLAG_BAR = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/anon_enum_allowlist_item.rs b/bindgen-tests/tests/expectations/tests/anon_enum_allowlist_item.rs new file mode 100644 index 0000000000..4d28c3abc7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_enum_allowlist_item.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const NODE_FLAG_FOO: _bindgen_ty_1 = 0; +pub const NODE_FLAG_BAR: _bindgen_ty_1 = 1; +pub type _bindgen_ty_1 = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/anon_enum_blocklist.rs b/bindgen-tests/tests/expectations/tests/anon_enum_blocklist.rs new file mode 100644 index 0000000000..28ab3ad786 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_enum_blocklist.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FLAG_Z: _bindgen_ty_2 = 0; +pub const FLAG_W: _bindgen_ty_2 = 1; +pub type _bindgen_ty_2 = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/anon_enum_trait.rs b/bindgen-tests/tests/expectations/tests/anon_enum_trait.rs new file mode 100644 index 0000000000..cfd4d03200 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_enum_trait.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct DataType { + pub _address: u8, +} +pub type DataType_value_type<_Tp> = _Tp; +pub type DataType_work_type<_Tp> = DataType_value_type<_Tp>; +pub type DataType_channel_type<_Tp> = DataType_value_type<_Tp>; +pub type DataType_vec_type<_Tp> = DataType_value_type<_Tp>; +pub const DataType_generic_type: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; +pub const DataType_depth: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; +pub const DataType_channels: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; +pub const DataType_fmt: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; +pub const DataType_type_: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum DataType__bindgen_ty_1 { + generic_type = 0, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_Bar: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar; +pub const Foo_Baz: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo__bindgen_ty_1 { + Bar = 0, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/anon_struct_in_union.rs b/bindgen-tests/tests/expectations/tests/anon_struct_in_union.rs new file mode 100644 index 0000000000..dceca1adf3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_struct_in_union.rs @@ -0,0 +1,60 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct s { + pub u: s__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union s__bindgen_ty_1 { + pub field: s__bindgen_ty_1_inner, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct s__bindgen_ty_1_inner { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of s__bindgen_ty_1_inner", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of s__bindgen_ty_1_inner", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: s__bindgen_ty_1_inner::b", + ][::std::mem::offset_of!(s__bindgen_ty_1_inner, b) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of s__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + ["Alignment of s__bindgen_ty_1"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: s__bindgen_ty_1::field", + ][::std::mem::offset_of!(s__bindgen_ty_1, field) - 0usize]; +}; +impl Default for s__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of s"][::std::mem::size_of::() - 4usize]; + ["Alignment of s"][::std::mem::align_of::() - 4usize]; + ["Offset of field: s::u"][::std::mem::offset_of!(s, u) - 0usize]; +}; +impl Default for s { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/anon_union.rs b/bindgen-tests/tests/expectations/tests/anon_union.rs new file mode 100644 index 0000000000..d9bf3cf183 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anon_union.rs @@ -0,0 +1,76 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct TErrorResult { + pub mResult: ::std::os::raw::c_int, + pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, + pub mMightHaveUnreported: bool, + pub mUnionState: TErrorResult_UnionState, +} +impl TErrorResult_UnionState { + pub const HasException: TErrorResult_UnionState = TErrorResult_UnionState::HasMessage; +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum TErrorResult_UnionState { + HasMessage = 0, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult_Message { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult_DOMExceptionInfo { + _unused: [u8; 0], +} +#[repr(C)] +pub union TErrorResult__bindgen_ty_1 { + pub mMessage: *mut TErrorResult_Message, + pub mDOMExceptionInfo: *mut TErrorResult_DOMExceptionInfo, +} +impl Default for TErrorResult__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for TErrorResult { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct ErrorResult { + pub _base: TErrorResult, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ErrorResult"][::std::mem::size_of::() - 24usize]; + ["Alignment of ErrorResult"][::std::mem::align_of::() - 8usize]; +}; +impl Default for ErrorResult { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: TErrorResult_open0_int_close0", + ][::std::mem::size_of::() - 24usize]; + [ + "Align of template specialization: TErrorResult_open0_int_close0", + ][::std::mem::align_of::() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/anonymous-template-types.rs b/bindgen-tests/tests/expectations/tests/anonymous-template-types.rs new file mode 100644 index 0000000000..f6c894d8b5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/anonymous-template-types.rs @@ -0,0 +1,42 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t_member: T, +} +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Bar { + pub member: ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Quux { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub v_member: V, +} +impl Default for Quux { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Lobo { + pub also_member: ::std::os::raw::c_char, +} +pub type AliasWithAnonType = ::std::os::raw::c_char; diff --git a/bindgen-tests/tests/expectations/tests/arg_keyword.rs b/bindgen-tests/tests/expectations/tests/arg_keyword.rs new file mode 100644 index 0000000000..5a48aba011 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/arg_keyword.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooPKc"] + pub fn foo(type_: *const ::std::os::raw::c_char); +} diff --git a/bindgen-tests/tests/expectations/tests/array-of-zero-sized-types.rs b/bindgen-tests/tests/expectations/tests/array-of-zero-sized-types.rs new file mode 100644 index 0000000000..4630abd275 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/array-of-zero-sized-types.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// This should get an `_address` byte. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Empty { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Empty"][::std::mem::size_of::() - 1usize]; + ["Alignment of Empty"][::std::mem::align_of::() - 1usize]; +}; +/** This should not get an `_address` byte, since each `Empty` gets one, meaning + that this object is addressable.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct HasArrayOfEmpty { + pub empties: [Empty; 10usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of HasArrayOfEmpty"][::std::mem::size_of::() - 10usize]; + ["Alignment of HasArrayOfEmpty"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: HasArrayOfEmpty::empties", + ][::std::mem::offset_of!(HasArrayOfEmpty, empties) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/atomic-constant.rs b/bindgen-tests/tests/expectations/tests/atomic-constant.rs new file mode 100644 index 0000000000..344e632085 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/atomic-constant.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut a: ::std::os::raw::c_int; +} +unsafe extern "C" { + pub static mut b: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/attribute-custom-cli.rs b/bindgen-tests/tests/expectations/tests/attribute-custom-cli.rs new file mode 100644 index 0000000000..55353116d3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/attribute-custom-cli.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[doc(hidden)] +#[derive(Default)] +pub struct foo_struct { + pub inner: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo_struct"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo_struct"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo_struct::inner", + ][::std::mem::offset_of!(foo_struct, inner) - 0usize]; +}; +#[repr(u32)] +#[cfg_attr(test, derive(PartialOrd, Copy))] +#[derive(Clone, Hash, PartialEq, Eq)] +pub enum foo_enum { + inner = 0, +} +#[repr(C)] +#[doc(hidden)] +#[derive(Clone)] +#[derive(Copy)] +pub union foo_union { + pub fst: ::std::mem::ManuallyDrop<::std::os::raw::c_int>, + pub snd: ::std::mem::ManuallyDrop, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo_union"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo_union"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo_union::fst"][::std::mem::offset_of!(foo_union, fst) - 0usize]; + ["Offset of field: foo_union::snd"][::std::mem::offset_of!(foo_union, snd) - 0usize]; +}; +#[repr(C)] +pub struct non_matching { + pub inner: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of non_matching"][::std::mem::size_of::() - 4usize]; + ["Alignment of non_matching"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: non_matching::inner", + ][::std::mem::offset_of!(non_matching, inner) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/attribute-custom.rs b/bindgen-tests/tests/expectations/tests/attribute-custom.rs new file mode 100644 index 0000000000..6d616d3f3e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/attribute-custom.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Debug)] +pub struct my_type { + pub a: ::std::os::raw::c_int, +} +/**
+
*/ +#[repr(C)] +#[derive(Debug)] +#[derive(Clone)] +pub struct my_type2 { + pub a: ::std::os::raw::c_uint, +} +///
+#[repr(C)] +#[derive(Debug)] +#[derive(Clone)] +pub struct my_type3 { + pub a: ::std::os::raw::c_ulong, +} diff --git a/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result.rs b/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result.rs new file mode 100644 index 0000000000..ec152e1543 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[must_use] + #[link_name = "\u{1}_ZN3Foo3fooEi"] + pub fn Foo_foo(this: *mut Foo, arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + #[must_use] + pub unsafe fn foo(&mut self, arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + Foo_foo(self, arg1) + } +} +unsafe extern "C" { + #[must_use] + #[link_name = "\u{1}_Z3fooi"] + pub fn foo(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result_no_attribute_detection.rs b/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result_no_attribute_detection.rs new file mode 100644 index 0000000000..f0fb434bcb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/attribute_warn_unused_result_no_attribute_detection.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo3fooEi"] + pub fn Foo_foo(this: *mut Foo, arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn foo(&mut self, arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + Foo_foo(self, arg1) + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooi"] + pub fn foo(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/auto.rs b/bindgen-tests/tests/expectations/tests/auto.rs new file mode 100644 index 0000000000..ba93e7a20b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/auto.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_kFoo: bool = true; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_Z5Test2v"] + pub fn Test2() -> ::std::os::raw::c_uint; +} diff --git a/bindgen-tests/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs b/bindgen-tests/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs new file mode 100644 index 0000000000..9ad8429e3c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct std_char_traits { + pub _address: u8, +} +impl Default for std_char_traits { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct __gnu_cxx_char_traits { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/base-to-derived.rs b/bindgen-tests/tests/expectations/tests/base-to-derived.rs new file mode 100644 index 0000000000..22ef4fdb08 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/base-to-derived.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct false_type { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of false_type"][::std::mem::size_of::() - 1usize]; + ["Alignment of false_type"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/bindgen-union-inside-namespace.rs b/bindgen-tests/tests/expectations/tests/bindgen-union-inside-namespace.rs new file mode 100644 index 0000000000..2c8d2e5713 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bindgen-union-inside-namespace.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Copy, Clone)] + pub union Bar { + pub foo: ::std::os::raw::c_int, + pub bar: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::foo"][::std::mem::offset_of!(Bar, foo) - 0usize]; + ["Offset of field: Bar::bar"][::std::mem::offset_of!(Bar, bar) - 0usize]; + }; + impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs new file mode 100644 index 0000000000..783f0ef7a9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs @@ -0,0 +1,1673 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct MuchBitfield { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of MuchBitfield"][::std::mem::size_of::() - 5usize]; + ["Alignment of MuchBitfield"][::std::mem::align_of::() - 1usize]; +}; +impl MuchBitfield { + #[inline] + pub fn m0(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_m0(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m0_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m0_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m1(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub fn set_m1(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m1_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m1_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m2(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } + } + #[inline] + pub fn set_m2(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m2_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m2_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m3(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) } + } + #[inline] + pub fn set_m3(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m3_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m3_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m4(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) } + } + #[inline] + pub fn set_m4(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m4_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m4_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m5(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) } + } + #[inline] + pub fn set_m5(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m5_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 5usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m5_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 5usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m6(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) } + } + #[inline] + pub fn set_m6(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m6_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 6usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m6_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 6usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m7(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) } + } + #[inline] + pub fn set_m7(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m7_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m7_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m8(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u8) } + } + #[inline] + pub fn set_m8(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m8_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m8_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m9(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u8) } + } + #[inline] + pub fn set_m9(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m9_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_m9_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m10(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u8) } + } + #[inline] + pub fn set_m10(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(10usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m10_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 10usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m10_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 10usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m11(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u8) } + } + #[inline] + pub fn set_m11(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(11usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m11_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 11usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m11_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 11usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m12(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u8) } + } + #[inline] + pub fn set_m12(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m12_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 12usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m12_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 12usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m13(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u8) } + } + #[inline] + pub fn set_m13(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(13usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m13_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 13usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m13_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 13usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m14(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u8) } + } + #[inline] + pub fn set_m14(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(14usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m14_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 14usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m14_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 14usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m15(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u8) } + } + #[inline] + pub fn set_m15(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(15usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m15_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 15usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m15_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 15usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m16(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 1u8) as u8) } + } + #[inline] + pub fn set_m16(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m16_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m16_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m17(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(17usize, 1u8) as u8) } + } + #[inline] + pub fn set_m17(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(17usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m17_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 17usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m17_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 17usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m18(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(18usize, 1u8) as u8) } + } + #[inline] + pub fn set_m18(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(18usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m18_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 18usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m18_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 18usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m19(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 1u8) as u8) } + } + #[inline] + pub fn set_m19(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(19usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m19_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 19usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m19_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 19usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m20(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 1u8) as u8) } + } + #[inline] + pub fn set_m20(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(20usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m20_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 20usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m20_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 20usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m21(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 1u8) as u8) } + } + #[inline] + pub fn set_m21(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(21usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m21_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 21usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m21_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 21usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m22(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(22usize, 1u8) as u8) } + } + #[inline] + pub fn set_m22(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(22usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m22_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 22usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m22_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 22usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m23(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(23usize, 1u8) as u8) } + } + #[inline] + pub fn set_m23(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(23usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m23_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 23usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m23_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 23usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m24(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 1u8) as u8) } + } + #[inline] + pub fn set_m24(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m24_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m24_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m25(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(25usize, 1u8) as u8) } + } + #[inline] + pub fn set_m25(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(25usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m25_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 25usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m25_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 25usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m26(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(26usize, 1u8) as u8) } + } + #[inline] + pub fn set_m26(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(26usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m26_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 26usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m26_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 26usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m27(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(27usize, 1u8) as u8) } + } + #[inline] + pub fn set_m27(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(27usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m27_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 27usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m27_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 27usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m28(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 1u8) as u8) } + } + #[inline] + pub fn set_m28(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(28usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m28_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 28usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m28_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 28usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m29(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u8) } + } + #[inline] + pub fn set_m29(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(29usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m29_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 29usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m29_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 29usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m30(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u8) } + } + #[inline] + pub fn set_m30(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(30usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m30_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 30usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m30_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 30usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m31(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } + } + #[inline] + pub fn set_m31(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(31usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m31_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 31usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m31_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 31usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn m32(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 1u8) as u8) } + } + #[inline] + pub fn set_m32(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(32usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn m32_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 32usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_m32_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 5usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 32usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + m0: ::std::os::raw::c_char, + m1: ::std::os::raw::c_char, + m2: ::std::os::raw::c_char, + m3: ::std::os::raw::c_char, + m4: ::std::os::raw::c_char, + m5: ::std::os::raw::c_char, + m6: ::std::os::raw::c_char, + m7: ::std::os::raw::c_char, + m8: ::std::os::raw::c_char, + m9: ::std::os::raw::c_char, + m10: ::std::os::raw::c_char, + m11: ::std::os::raw::c_char, + m12: ::std::os::raw::c_char, + m13: ::std::os::raw::c_char, + m14: ::std::os::raw::c_char, + m15: ::std::os::raw::c_char, + m16: ::std::os::raw::c_char, + m17: ::std::os::raw::c_char, + m18: ::std::os::raw::c_char, + m19: ::std::os::raw::c_char, + m20: ::std::os::raw::c_char, + m21: ::std::os::raw::c_char, + m22: ::std::os::raw::c_char, + m23: ::std::os::raw::c_char, + m24: ::std::os::raw::c_char, + m25: ::std::os::raw::c_char, + m26: ::std::os::raw::c_char, + m27: ::std::os::raw::c_char, + m28: ::std::os::raw::c_char, + m29: ::std::os::raw::c_char, + m30: ::std::os::raw::c_char, + m31: ::std::os::raw::c_char, + m32: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 5usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 5usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let m0: u8 = unsafe { ::std::mem::transmute(m0) }; + m0 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let m1: u8 = unsafe { ::std::mem::transmute(m1) }; + m1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let m2: u8 = unsafe { ::std::mem::transmute(m2) }; + m2 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 1u8, + { + let m3: u8 = unsafe { ::std::mem::transmute(m3) }; + m3 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 1u8, + { + let m4: u8 = unsafe { ::std::mem::transmute(m4) }; + m4 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 5usize, + 1u8, + { + let m5: u8 = unsafe { ::std::mem::transmute(m5) }; + m5 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 1u8, + { + let m6: u8 = unsafe { ::std::mem::transmute(m6) }; + m6 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 1u8, + { + let m7: u8 = unsafe { ::std::mem::transmute(m7) }; + m7 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 1u8, + { + let m8: u8 = unsafe { ::std::mem::transmute(m8) }; + m8 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 1u8, + { + let m9: u8 = unsafe { ::std::mem::transmute(m9) }; + m9 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 10usize, + 1u8, + { + let m10: u8 = unsafe { ::std::mem::transmute(m10) }; + m10 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 11usize, + 1u8, + { + let m11: u8 = unsafe { ::std::mem::transmute(m11) }; + m11 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 12usize, + 1u8, + { + let m12: u8 = unsafe { ::std::mem::transmute(m12) }; + m12 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 13usize, + 1u8, + { + let m13: u8 = unsafe { ::std::mem::transmute(m13) }; + m13 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 1u8, + { + let m14: u8 = unsafe { ::std::mem::transmute(m14) }; + m14 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 15usize, + 1u8, + { + let m15: u8 = unsafe { ::std::mem::transmute(m15) }; + m15 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 1u8, + { + let m16: u8 = unsafe { ::std::mem::transmute(m16) }; + m16 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 17usize, + 1u8, + { + let m17: u8 = unsafe { ::std::mem::transmute(m17) }; + m17 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 18usize, + 1u8, + { + let m18: u8 = unsafe { ::std::mem::transmute(m18) }; + m18 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 19usize, + 1u8, + { + let m19: u8 = unsafe { ::std::mem::transmute(m19) }; + m19 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 20usize, + 1u8, + { + let m20: u8 = unsafe { ::std::mem::transmute(m20) }; + m20 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 21usize, + 1u8, + { + let m21: u8 = unsafe { ::std::mem::transmute(m21) }; + m21 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 22usize, + 1u8, + { + let m22: u8 = unsafe { ::std::mem::transmute(m22) }; + m22 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 23usize, + 1u8, + { + let m23: u8 = unsafe { ::std::mem::transmute(m23) }; + m23 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 1u8, + { + let m24: u8 = unsafe { ::std::mem::transmute(m24) }; + m24 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 25usize, + 1u8, + { + let m25: u8 = unsafe { ::std::mem::transmute(m25) }; + m25 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 26usize, + 1u8, + { + let m26: u8 = unsafe { ::std::mem::transmute(m26) }; + m26 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 27usize, + 1u8, + { + let m27: u8 = unsafe { ::std::mem::transmute(m27) }; + m27 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 28usize, + 1u8, + { + let m28: u8 = unsafe { ::std::mem::transmute(m28) }; + m28 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 29usize, + 1u8, + { + let m29: u8 = unsafe { ::std::mem::transmute(m29) }; + m29 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 30usize, + 1u8, + { + let m30: u8 = unsafe { ::std::mem::transmute(m30) }; + m30 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 31usize, + 1u8, + { + let m31: u8 = unsafe { ::std::mem::transmute(m31) }; + m31 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 32usize, + 1u8, + { + let m32: u8 = unsafe { ::std::mem::transmute(m32) }; + m32 as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/tests/expectations/tests/bitfield-enum-basic.rs b/bindgen-tests/tests/expectations/tests/bitfield-enum-basic.rs similarity index 80% rename from tests/expectations/tests/bitfield-enum-basic.rs rename to bindgen-tests/tests/expectations/tests/bitfield-enum-basic.rs index a8140b2eb0..aecb9dc639 100644 --- a/tests/expectations/tests/bitfield-enum-basic.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield-enum-basic.rs @@ -1,17 +1,8 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - impl Foo { pub const Bar: Foo = Foo(2); -} -impl Foo { pub const Baz: Foo = Foo(4); -} -impl Foo { pub const Duplicated: Foo = Foo(4); -} -impl Foo { pub const Negative: Foo = Foo(-3); } impl ::std::ops::BitOr for Foo { @@ -40,19 +31,13 @@ impl ::std::ops::BitAndAssign for Foo { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Foo(pub i32); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_int); impl Buz { pub const Bar: Buz = Buz(2); -} -impl Buz { pub const Baz: Buz = Buz(4); -} -impl Buz { pub const Duplicated: Buz = Buz(4); -} -impl Buz { pub const Negative: Buz = Buz(-3); } impl ::std::ops::BitOr for Buz { @@ -81,9 +66,9 @@ impl ::std::ops::BitAndAssign for Buz { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Buz(pub i8); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Buz(pub ::std::os::raw::c_schar); pub const NS_FOO: _bindgen_ty_1 = _bindgen_ty_1(1); pub const NS_BAR: _bindgen_ty_1 = _bindgen_ty_1(2); impl ::std::ops::BitOr<_bindgen_ty_1> for _bindgen_ty_1 { @@ -112,9 +97,9 @@ impl ::std::ops::BitAndAssign for _bindgen_ty_1 { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct _bindgen_ty_1(pub u32); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct _bindgen_ty_1(pub ::std::os::raw::c_uint); #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Dummy { @@ -148,19 +133,11 @@ impl ::std::ops::BitAndAssign for Dummy__bindgen_ty_1 { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Dummy__bindgen_ty_1(pub u32); -#[test] -fn bindgen_test_layout_Dummy() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Dummy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Dummy)) - ); -} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Dummy__bindgen_ty_1(pub ::std::os::raw::c_uint); +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Dummy"][::std::mem::size_of::() - 1usize]; + ["Alignment of Dummy"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-c.rs b/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-c.rs new file mode 100644 index 0000000000..df5a69eddd --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-c.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl Foo { + pub const Bar: Foo = Foo(2); + pub const Baz: Foo = Foo(4); + pub const Duplicated: Foo = Foo(4); + pub const Negative: Foo = Foo(-3); +} +impl ::std::ops::BitOr for Foo { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Foo { + #[inline] + fn bitor_assign(&mut self, rhs: Foo) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Foo { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Foo { + #[inline] + fn bitand_assign(&mut self, rhs: Foo) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_int); diff --git a/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-transparent.rs b/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-transparent.rs new file mode 100644 index 0000000000..df5a69eddd --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-enum-repr-transparent.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl Foo { + pub const Bar: Foo = Foo(2); + pub const Baz: Foo = Foo(4); + pub const Duplicated: Foo = Foo(4); + pub const Negative: Foo = Foo(-3); +} +impl ::std::ops::BitOr for Foo { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Foo { + #[inline] + fn bitor_assign(&mut self, rhs: Foo) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Foo { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Foo { + #[inline] + fn bitand_assign(&mut self, rhs: Foo) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_int); diff --git a/bindgen-tests/tests/expectations/tests/bitfield-large.rs b/bindgen-tests/tests/expectations/tests/bitfield-large.rs new file mode 100644 index 0000000000..5d614ab936 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-large.rs @@ -0,0 +1,322 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct HasBigBitfield { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of HasBigBitfield"][::std::mem::size_of::() - 16usize]; + ["Alignment of HasBigBitfield"][::std::mem::align_of::() - 16usize]; +}; +impl HasBigBitfield { + #[inline] + pub fn x(&self) -> i128 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 128u8) as u128) } + } + #[inline] + pub fn set_x(&mut self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 128u8, val as u64) + } + } + #[inline] + pub unsafe fn x_raw(this: *const Self) -> i128 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 128u8) + as u128, + ) + } + } + #[inline] + pub unsafe fn set_x_raw(this: *mut Self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 128u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(x: i128) -> __BindgenBitfieldUnit<[u8; 16usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 128u8, + { + let x: u128 = unsafe { ::std::mem::transmute(x) }; + x as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct HasTwoBigBitfields { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of HasTwoBigBitfields", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of HasTwoBigBitfields", + ][::std::mem::align_of::() - 16usize]; +}; +impl HasTwoBigBitfields { + #[inline] + pub fn x(&self) -> i128 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 80u8) as u128) } + } + #[inline] + pub fn set_x(&mut self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 80u8, val as u64) + } + } + #[inline] + pub unsafe fn x_raw(this: *const Self) -> i128 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 80u8) + as u128, + ) + } + } + #[inline] + pub unsafe fn set_x_raw(this: *mut Self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 80u8, + val as u64, + ) + } + } + #[inline] + pub fn y(&self) -> i128 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(80usize, 48u8) as u128) } + } + #[inline] + pub fn set_y(&mut self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + self._bitfield_1.set(80usize, 48u8, val as u64) + } + } + #[inline] + pub unsafe fn y_raw(this: *const Self) -> i128 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 80usize, 48u8) + as u128, + ) + } + } + #[inline] + pub unsafe fn set_y_raw(this: *mut Self, val: i128) { + unsafe { + let val: u128 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 80usize, + 48u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(x: i128, y: i128) -> __BindgenBitfieldUnit<[u8; 16usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 80u8, + { + let x: u128 = unsafe { ::std::mem::transmute(x) }; + x as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 80usize, + 48u8, + { + let y: u128 = unsafe { ::std::mem::transmute(y) }; + y as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs b/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs new file mode 100644 index 0000000000..3e676c53b5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs @@ -0,0 +1,250 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test { + pub foo: u64, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +impl Test { + #[inline] + pub fn x(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 56u8) as u64) } + } + #[inline] + pub fn set_x(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 56u8, val as u64) + } + } + #[inline] + pub unsafe fn x_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 56u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_x_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 56u8, + val as u64, + ) + } + } + #[inline] + pub fn y(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(56usize, 8u8) as u64) } + } + #[inline] + pub fn set_y(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(56usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn y_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 56usize, 8u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_y_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 56usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(x: u64, y: u64) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 56u8, + { + let x: u64 = unsafe { ::std::mem::transmute(x) }; + x as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 56usize, + 8u8, + { + let y: u64 = unsafe { ::std::mem::transmute(y) }; + y as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs new file mode 100644 index 0000000000..09ca005589 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs @@ -0,0 +1,241 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo4typeEv"] + pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_char; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo9set_type_Ec"] + pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_char); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo8set_typeEc"] + pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_char); +} +impl Foo { + #[inline] + pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u8) } + } + #[inline] + pub fn set_type__bindgen_bitfield(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn type__bindgen_bitfield_raw( + this: *const Self, + ) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 3u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_type__bindgen_bitfield_raw( + this: *mut Self, + val: ::std::os::raw::c_char, + ) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + type__bindgen_bitfield: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let type__bindgen_bitfield: u8 = unsafe { + ::std::mem::transmute(type__bindgen_bitfield) + }; + type__bindgen_bitfield as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub unsafe fn type_(&mut self) -> ::std::os::raw::c_char { + Foo_type(self) + } + #[inline] + pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_char) { + Foo_set_type_(self, c) + } + #[inline] + pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_char) { + Foo_set_type(self, c) + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield-template.rs b/bindgen-tests/tests/expectations/tests/bitfield-template.rs new file mode 100644 index 0000000000..eb454e0db4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-template.rs @@ -0,0 +1,214 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl foo { + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 8u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 8u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align.rs b/bindgen-tests/tests/expectations/tests/bitfield_align.rs new file mode 100644 index 0000000000..0c70917fc5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_align.rs @@ -0,0 +1,1513 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _bindgen_align: [u32; 0], + pub x: ::std::os::raw::c_uchar, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub y: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 4usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::x"][::std::mem::offset_of!(A, x) - 0usize]; + ["Offset of field: A::y"][::std::mem::offset_of!(A, y) - 3usize]; +}; +impl A { + #[inline] + pub fn b1(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_b1(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b1_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b1_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b2(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_b2(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b2_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b2_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b3(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } + } + #[inline] + pub fn set_b3(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b3_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b3_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b4(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } + } + #[inline] + pub fn set_b4(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b4_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b4_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b5(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) } + } + #[inline] + pub fn set_b5(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b5_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b5_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b6(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) } + } + #[inline] + pub fn set_b6(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b6_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 5usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b6_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 5usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b7(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) } + } + #[inline] + pub fn set_b7(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b7_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 6usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b7_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 6usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b8(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) } + } + #[inline] + pub fn set_b8(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b8_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b8_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b9(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) } + } + #[inline] + pub fn set_b9(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b9_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b9_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b10(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) } + } + #[inline] + pub fn set_b10(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b10_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b10_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + b1: ::std::os::raw::c_uint, + b2: ::std::os::raw::c_uint, + b3: ::std::os::raw::c_uint, + b4: ::std::os::raw::c_uint, + b5: ::std::os::raw::c_uint, + b6: ::std::os::raw::c_uint, + b7: ::std::os::raw::c_uint, + b8: ::std::os::raw::c_uint, + b9: ::std::os::raw::c_uint, + b10: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let b1: u32 = unsafe { ::std::mem::transmute(b1) }; + b1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b2: u32 = unsafe { ::std::mem::transmute(b2) }; + b2 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let b3: u32 = unsafe { ::std::mem::transmute(b3) }; + b3 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 1u8, + { + let b4: u32 = unsafe { ::std::mem::transmute(b4) }; + b4 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 1u8, + { + let b5: u32 = unsafe { ::std::mem::transmute(b5) }; + b5 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 5usize, + 1u8, + { + let b6: u32 = unsafe { ::std::mem::transmute(b6) }; + b6 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 1u8, + { + let b7: u32 = unsafe { ::std::mem::transmute(b7) }; + b7 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 1u8, + { + let b8: u32 = unsafe { ::std::mem::transmute(b8) }; + b8 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 1u8, + { + let b9: u32 = unsafe { ::std::mem::transmute(b9) }; + b9 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 1u8, + { + let b10: u32 = unsafe { ::std::mem::transmute(b10) }; + b10 as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct B { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 4usize]; + ["Alignment of B"][::std::mem::align_of::() - 4usize]; +}; +impl B { + #[inline] + pub fn foo(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 31u8) as u32) } + } + #[inline] + pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 31u8, val as u64) + } + } + #[inline] + pub unsafe fn foo_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 31u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_foo_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 31u8, + val as u64, + ) + } + } + #[inline] + pub fn bar(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } + } + #[inline] + pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(31usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bar_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 31usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_bar_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 31usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + foo: ::std::os::raw::c_uint, + bar: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 31u8, + { + let foo: u32 = unsafe { ::std::mem::transmute(foo) }; + foo as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 31usize, + 1u8, + { + let bar: u8 = unsafe { ::std::mem::transmute(bar) }; + bar as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub x: ::std::os::raw::c_uchar, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub baz: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 8usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::x"][::std::mem::offset_of!(C, x) - 0usize]; + ["Offset of field: C::baz"][::std::mem::offset_of!(C, baz) - 4usize]; +}; +impl C { + #[inline] + pub fn b1(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_b1(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b1_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b1_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b2(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_b2(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b2_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b2_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + b1: ::std::os::raw::c_uint, + b2: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let b1: u32 = unsafe { ::std::mem::transmute(b1) }; + b1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b2: u32 = unsafe { ::std::mem::transmute(b2) }; + b2 as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Date1 { + pub _bindgen_align: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub __bindgen_padding_0: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Date1"][::std::mem::size_of::() - 4usize]; + ["Alignment of Date1"][::std::mem::align_of::() - 2usize]; +}; +impl Date1 { + #[inline] + pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } + } + #[inline] + pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn nWeekDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nWeekDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } + } + #[inline] + pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 6u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonthDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 6u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonthDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 6u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonth(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } + } + #[inline] + pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 5u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonth_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 5u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonth_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 5u8, + val as u64, + ) + } + } + #[inline] + pub fn nYear(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } + } + #[inline] + pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn nYear_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 8u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nYear_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + nWeekDay: ::std::os::raw::c_ushort, + nMonthDay: ::std::os::raw::c_ushort, + nMonth: ::std::os::raw::c_ushort, + nYear: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; + nWeekDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 6u8, + { + let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; + nMonthDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 5u8, + { + let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; + nMonth as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 8u8, + { + let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; + nYear as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Date2 { + pub _bindgen_align: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Date2"][::std::mem::size_of::() - 4usize]; + ["Alignment of Date2"][::std::mem::align_of::() - 2usize]; +}; +impl Date2 { + #[inline] + pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } + } + #[inline] + pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn nWeekDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nWeekDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } + } + #[inline] + pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 6u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonthDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 6u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonthDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 6u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonth(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } + } + #[inline] + pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 5u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonth_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 5u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonth_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 5u8, + val as u64, + ) + } + } + #[inline] + pub fn nYear(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } + } + #[inline] + pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn nYear_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 8u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nYear_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn byte(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u8) } + } + #[inline] + pub fn set_byte(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn byte_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 8u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_byte_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + nWeekDay: ::std::os::raw::c_ushort, + nMonthDay: ::std::os::raw::c_ushort, + nMonth: ::std::os::raw::c_ushort, + nYear: ::std::os::raw::c_ushort, + byte: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; + nWeekDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 6u8, + { + let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; + nMonthDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 5u8, + { + let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; + nMonth as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 8u8, + { + let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; + nYear as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 8u8, + { + let byte: u8 = unsafe { ::std::mem::transmute(byte) }; + byte as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Date3 { + pub _bindgen_align: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub byte: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Date3"][::std::mem::size_of::() - 4usize]; + ["Alignment of Date3"][::std::mem::align_of::() - 2usize]; + ["Offset of field: Date3::byte"][::std::mem::offset_of!(Date3, byte) - 3usize]; +}; +impl Date3 { + #[inline] + pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } + } + #[inline] + pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn nWeekDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nWeekDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } + } + #[inline] + pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 6u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonthDay_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 6u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonthDay_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 6u8, + val as u64, + ) + } + } + #[inline] + pub fn nMonth(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } + } + #[inline] + pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 5u8, val as u64) + } + } + #[inline] + pub unsafe fn nMonth_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 5u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nMonth_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 5u8, + val as u64, + ) + } + } + #[inline] + pub fn nYear(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } + } + #[inline] + pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn nYear_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 8u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_nYear_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + nWeekDay: ::std::os::raw::c_ushort, + nMonthDay: ::std::os::raw::c_ushort, + nMonth: ::std::os::raw::c_ushort, + nYear: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; + nWeekDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 6u8, + { + let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; + nMonthDay as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 5u8, + { + let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; + nMonth as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 8u8, + { + let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; + nYear as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs new file mode 100644 index 0000000000..b71bba18ad --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs @@ -0,0 +1,276 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(target_os = "windows"))] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MyEnum { + ONE = 0, + TWO = 1, + THREE = 2, + FOUR = 3, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TaggedPtr { + pub _bindgen_align: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TaggedPtr"][::std::mem::size_of::() - 8usize]; + ["Alignment of TaggedPtr"][::std::mem::align_of::() - 8usize]; +}; +impl Default for TaggedPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl TaggedPtr { + #[inline] + pub fn tag(&self) -> MyEnum { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u32) } + } + #[inline] + pub fn set_tag(&mut self, val: MyEnum) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn tag_raw(this: *const Self) -> MyEnum { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 2u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_tag_raw(this: *mut Self, val: MyEnum) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn ptr(&self) -> ::std::os::raw::c_long { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 62u8) as u64) } + } + #[inline] + pub fn set_ptr(&mut self, val: ::std::os::raw::c_long) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 62u8, val as u64) + } + } + #[inline] + pub unsafe fn ptr_raw(this: *const Self) -> ::std::os::raw::c_long { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 62u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_ptr_raw(this: *mut Self, val: ::std::os::raw::c_long) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 62u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + tag: MyEnum, + ptr: ::std::os::raw::c_long, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 2u8, + { + let tag: u32 = unsafe { ::std::mem::transmute(tag) }; + tag as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 62u8, + { + let ptr: u64 = unsafe { ::std::mem::transmute(ptr) }; + ptr as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs b/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs new file mode 100644 index 0000000000..ac5d75735e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct _bindgen_ty_1 { + pub _bindgen_align: [u64; 0], + pub _bindgen_opaque_blob: __BindgenOpaqueArray8<[u8; 80usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 80usize]; + ["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 8usize]; +}; +unsafe extern "C" { + pub static mut a: _bindgen_ty_1; +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs new file mode 100644 index 0000000000..35117c74b6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs @@ -0,0 +1,262 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct mach_msg_type_descriptor_t { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of mach_msg_type_descriptor_t", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of mach_msg_type_descriptor_t", + ][::std::mem::align_of::() - 4usize]; +}; +impl mach_msg_type_descriptor_t { + #[inline] + pub fn pad3(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) } + } + #[inline] + pub fn set_pad3(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 24u8, val as u64) + } + } + #[inline] + pub unsafe fn pad3_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 24u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_pad3_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 24u8, + val as u64, + ) + } + } + #[inline] + pub fn type_(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) } + } + #[inline] + pub fn set_type(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn type__raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 8u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_type_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + pad3: ::std::os::raw::c_uint, + type_: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 24u8, + { + let pad3: u32 = unsafe { ::std::mem::transmute(pad3) }; + pad3 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 8u8, + { + let type_: u32 = unsafe { ::std::mem::transmute(type_) }; + type_ as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs b/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs new file mode 100644 index 0000000000..d654e25b27 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs @@ -0,0 +1,507 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct A { + pub name: [::std::os::raw::c_uchar; 7usize], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub maxYield: ::std::os::raw::c_uchar, + pub _bitfield_2: __BindgenBitfieldUnit<[u8; 1usize]>, + pub description1: *const ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 24usize]; + ["Alignment of A"][::std::mem::align_of::() - 8usize]; + ["Offset of field: A::name"][::std::mem::offset_of!(A, name) - 0usize]; + ["Offset of field: A::maxYield"][::std::mem::offset_of!(A, maxYield) - 10usize]; + [ + "Offset of field: A::description1", + ][::std::mem::offset_of!(A, description1) - 16usize]; +}; +impl Default for A { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl A { + #[inline] + pub fn firmness(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) } + } + #[inline] + pub fn set_firmness(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn firmness_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_firmness_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn color(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) } + } + #[inline] + pub fn set_color(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn color_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_color_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn weedsBonus(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 3u8) as u16) } + } + #[inline] + pub fn set_weedsBonus(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn weedsBonus_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_weedsBonus_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn pestsBonus(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 3u8) as u16) } + } + #[inline] + pub fn set_pestsBonus(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(11usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn pestsBonus_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 11usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_pestsBonus_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 11usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn size(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 10u8) as u16) } + } + #[inline] + pub fn set_size(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(14usize, 10u8, val as u64) + } + } + #[inline] + pub unsafe fn size_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 14usize, 10u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_size_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 14usize, + 10u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + firmness: ::std::os::raw::c_uchar, + color: ::std::os::raw::c_uchar, + weedsBonus: ::std::os::raw::c_ushort, + pestsBonus: ::std::os::raw::c_ushort, + size: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let firmness: u8 = unsafe { ::std::mem::transmute(firmness) }; + firmness as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let color: u8 = unsafe { ::std::mem::transmute(color) }; + color as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 3u8, + { + let weedsBonus: u16 = unsafe { ::std::mem::transmute(weedsBonus) }; + weedsBonus as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 11usize, + 3u8, + { + let pestsBonus: u16 = unsafe { ::std::mem::transmute(pestsBonus) }; + pestsBonus as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 10u8, + { + let size: u16 = unsafe { ::std::mem::transmute(size) }; + size as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub fn minYield(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 4u8) as u8) } + } + #[inline] + pub fn set_minYield(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn minYield_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 0usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_minYield_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn waterBonus(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_2.get(4usize, 4u8) as u8) } + } + #[inline] + pub fn set_waterBonus(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn waterBonus_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 4usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_waterBonus_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_2( + minYield: ::std::os::raw::c_uchar, + waterBonus: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let minYield: u8 = unsafe { ::std::mem::transmute(minYield) }; + minYield as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let waterBonus: u8 = unsafe { ::std::mem::transmute(waterBonus) }; + waterBonus as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs new file mode 100644 index 0000000000..6f9adcb5ab --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs @@ -0,0 +1,514 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Struct { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Struct"][::std::mem::size_of::() - 4usize]; + ["Alignment of Struct"][::std::mem::align_of::() - 1usize]; +}; +impl Struct { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn c(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 6u8) as u8) } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 6u8, val as u64) + } + } + #[inline] + pub unsafe fn c_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 6u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_c_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 6u8, + val as u64, + ) + } + } + #[inline] + pub fn d(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 16u8) as u16) } + } + #[inline] + pub fn set_d(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn d_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 16u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_d_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn e(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u8) } + } + #[inline] + pub fn set_e(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn e_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 8u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_e_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_uchar, + b: ::std::os::raw::c_uchar, + c: ::std::os::raw::c_uchar, + d: ::std::os::raw::c_ushort, + e: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 6u8, + { + let c: u8 = unsafe { ::std::mem::transmute(c) }; + c as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 16u8, + { + let d: u16 = unsafe { ::std::mem::transmute(d) }; + d as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 8u8, + { + let e: u8 = unsafe { ::std::mem::transmute(e) }; + e as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Inner { + pub _bindgen_align: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Inner"][::std::mem::size_of::() - 4usize]; + ["Alignment of Inner"][::std::mem::align_of::() - 2usize]; +}; +impl Inner { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u16) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 16u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 16u8) as u16) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 16u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_ushort, + b: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 16u8, + { + let a: u16 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 16u8, + { + let b: u16 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer { + pub inner: Inner, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Outer"][::std::mem::size_of::() - 4usize]; + ["Alignment of Outer"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Outer::inner"][::std::mem::offset_of!(Outer, inner) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/block_return_type.rs b/bindgen-tests/tests/expectations/tests/block_return_type.rs new file mode 100644 index 0000000000..8ab2d70f11 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/block_return_type.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +extern crate block; +unsafe extern "C" { + pub fn func() -> _bindgen_ty_id_4; +} +pub type _bindgen_ty_id_4 = *const ::block::Block< + (::std::os::raw::c_int, ::std::os::raw::c_int), + ::std::os::raw::c_int, +>; diff --git a/bindgen-tests/tests/expectations/tests/blocklist-and-impl-debug.rs b/bindgen-tests/tests/expectations/tests/blocklist-and-impl-debug.rs new file mode 100644 index 0000000000..43e645bfc3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-and-impl-debug.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct BlocklistMe(u8); +/// Because this type contains a blocklisted type, it should not derive Debug. +#[repr(C)] +pub struct ShouldManuallyImplDebug { + pub a: BlocklistMe, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldManuallyImplDebug", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ShouldManuallyImplDebug", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ShouldManuallyImplDebug::a", + ][::std::mem::offset_of!(ShouldManuallyImplDebug, a) - 0usize]; +}; +impl Default for ShouldManuallyImplDebug { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for ShouldManuallyImplDebug { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "ShouldManuallyImplDebug {{ }}") + } +} diff --git a/bindgen-tests/tests/expectations/tests/blocklist-file.rs b/bindgen-tests/tests/expectations/tests/blocklist-file.rs new file mode 100644 index 0000000000..4056ef4d2c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-file.rs @@ -0,0 +1,39 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct SizedIntegers { + pub x: u8, + pub y: u16, + pub z: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of SizedIntegers"][::std::mem::size_of::() - 8usize]; + ["Alignment of SizedIntegers"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: SizedIntegers::x", + ][::std::mem::offset_of!(SizedIntegers, x) - 0usize]; + [ + "Offset of field: SizedIntegers::y", + ][::std::mem::offset_of!(SizedIntegers, y) - 2usize]; + [ + "Offset of field: SizedIntegers::z", + ][::std::mem::offset_of!(SizedIntegers, z) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct StructWithBlocklistedFwdDecl { + pub b: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of StructWithBlocklistedFwdDecl", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of StructWithBlocklistedFwdDecl", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: StructWithBlocklistedFwdDecl::b", + ][::std::mem::offset_of!(StructWithBlocklistedFwdDecl, b) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/blocklist-function.rs b/bindgen-tests/tests/expectations/tests/blocklist-function.rs new file mode 100644 index 0000000000..65b66b2ac2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-function.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + } + pub mod bar { + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN3bar18NamespacedFunctionEv"] + pub fn NamespacedFunction(); + } + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct C { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of C"][::std::mem::size_of::() - 1usize]; + ["Alignment of C"][::std::mem::align_of::() - 1usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/blocklist-item.rs b/bindgen-tests/tests/expectations/tests/blocklist-item.rs new file mode 100644 index 0000000000..c5daf050a1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-item.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + } + pub mod bar { + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN3bar18NamespacedFunctionEv"] + pub fn NamespacedFunction(); + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/blocklist-methods.rs b/bindgen-tests/tests/expectations/tests/blocklist-methods.rs new file mode 100644 index 0000000000..c89cadb3d5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-methods.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo3fooEv"] + pub fn Foo_foo(this: *mut Foo) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn foo(&mut self) -> ::std::os::raw::c_int { + Foo_foo(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/blocklist-var.rs b/bindgen-tests/tests/expectations/tests/blocklist-var.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist-var.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs b/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs new file mode 100644 index 0000000000..77c263e3cc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs @@ -0,0 +1,118 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[path = "./struct_with_bitfields.rs"] +mod bitfields; +use bitfields::*; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub x: ::std::os::raw::c_uchar, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub baz: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 8usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::x"][::std::mem::offset_of!(C, x) - 0usize]; + ["Offset of field: C::baz"][::std::mem::offset_of!(C, baz) - 4usize]; +}; +impl C { + #[inline] + pub fn b1(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_b1(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b1_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b1_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b2(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_b2(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b2_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b2_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + b1: ::std::os::raw::c_uint, + b2: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let b1: u32 = unsafe { ::std::mem::transmute(b1) }; + b1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b2: u32 = unsafe { ::std::mem::transmute(b2) }; + b2 as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/blocks-signature.rs b/bindgen-tests/tests/expectations/tests/blocks-signature.rs new file mode 100644 index 0000000000..93cf28e009 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocks-signature.rs @@ -0,0 +1,66 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +extern crate block; +unsafe extern "C" { + #[link_name = "\u{1}_Z8atexit_bU13block_pointerFvvE"] + pub fn atexit_b(arg1: _bindgen_ty_id_33); +} +pub type dispatch_data_t = *mut ::std::os::raw::c_void; +pub type dispatch_data_applier_t = _bindgen_ty_id_40; +unsafe extern "C" { + #[link_name = "\u{1}_Z19dispatch_data_applyPvU13block_pointerFbS_yPKvyE"] + pub fn dispatch_data_apply( + data: dispatch_data_t, + applier: dispatch_data_applier_t, + ) -> bool; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooU13block_pointerFvyE"] + pub fn foo(arg1: _bindgen_ty_id_50) -> bool; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z7foo_ptrPU13block_pointerFvyE"] + pub fn foo_ptr(arg1: *mut _bindgen_ty_id_56) -> bool; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct contains_block_pointers { + pub val: contains_block_pointers__bindgen_ty_id_61, + pub ptr_val: *mut _bindgen_ty_id_68, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of contains_block_pointers", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of contains_block_pointers", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: contains_block_pointers::val", + ][::std::mem::offset_of!(contains_block_pointers, val) - 0usize]; + [ + "Offset of field: contains_block_pointers::ptr_val", + ][::std::mem::offset_of!(contains_block_pointers, ptr_val) - 8usize]; +}; +impl Default for contains_block_pointers { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type _bindgen_ty_id_33 = *const ::block::Block<(), ()>; +pub type _bindgen_ty_id_40 = *const ::block::Block< + (dispatch_data_t, usize, *const ::std::os::raw::c_void, usize), + bool, +>; +pub type _bindgen_ty_id_50 = *const ::block::Block<(usize,), ()>; +pub type _bindgen_ty_id_56 = *const ::block::Block<(usize,), ()>; +pub type contains_block_pointers__bindgen_ty_id_61 = *const ::block::Block< + (::std::os::raw::c_int,), + (), +>; +pub type _bindgen_ty_id_68 = *const ::block::Block<(::std::os::raw::c_int,), ()>; diff --git a/bindgen-tests/tests/expectations/tests/blocks.rs b/bindgen-tests/tests/expectations/tests/blocks.rs new file mode 100644 index 0000000000..4f51113c4b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/blocks.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +unsafe extern "C" { + #[link_name = "\u{1}_Z8atexit_bU13block_pointerFvvE"] + pub fn atexit_b(arg1: *mut ::std::os::raw::c_void); +} +pub type dispatch_data_t = *mut ::std::os::raw::c_void; +pub type dispatch_data_applier_t = *mut ::std::os::raw::c_void; +unsafe extern "C" { + #[link_name = "\u{1}_Z19dispatch_data_applyPvU13block_pointerFbS_yPKvyE"] + pub fn dispatch_data_apply( + data: dispatch_data_t, + applier: dispatch_data_applier_t, + ) -> bool; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooU13block_pointerFvyE"] + pub fn foo(arg1: *mut ::std::os::raw::c_void) -> bool; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z7foo_ptrPU13block_pointerFvyE"] + pub fn foo_ptr(arg1: *mut *mut ::std::os::raw::c_void) -> bool; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct contains_block_pointers { + pub val: *mut ::std::os::raw::c_void, + pub ptr_val: *mut *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of contains_block_pointers", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of contains_block_pointers", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: contains_block_pointers::val", + ][::std::mem::offset_of!(contains_block_pointers, val) - 0usize]; + [ + "Offset of field: contains_block_pointers::ptr_val", + ][::std::mem::offset_of!(contains_block_pointers, ptr_val) - 8usize]; +}; +impl Default for contains_block_pointers { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/bug-1529681.rs b/bindgen-tests/tests/expectations/tests/bug-1529681.rs new file mode 100644 index 0000000000..bd59c1971f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bug-1529681.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct BrowsingContext { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of BrowsingContext"][::std::mem::size_of::() - 1usize]; + ["Alignment of BrowsingContext"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/builtin-template.rs b/bindgen-tests/tests/expectations/tests/builtin-template.rs new file mode 100644 index 0000000000..53e3fbf9bf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/builtin-template.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type std_make_integer_sequence = u8; diff --git a/bindgen-tests/tests/expectations/tests/c-empty-layout.rs b/bindgen-tests/tests/expectations/tests/c-empty-layout.rs new file mode 100644 index 0000000000..709a9a59d8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/c-empty-layout.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo {} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 0usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/c-unwind-abi-override.rs b/bindgen-tests/tests/expectations/tests/c-unwind-abi-override.rs new file mode 100644 index 0000000000..a158565033 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/c-unwind-abi-override.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C-unwind" { + pub fn foo(); +} +unsafe extern "C-unwind" { + pub fn bar(); +} +unsafe extern "C" { + pub fn baz(); +} diff --git a/bindgen-tests/tests/expectations/tests/c_naming.rs b/bindgen-tests/tests/expectations/tests/c_naming.rs new file mode 100644 index 0000000000..38e63ce874 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/c_naming.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct struct_a { + pub a: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of struct_a"][::std::mem::size_of::() - 4usize]; + ["Alignment of struct_a"][::std::mem::align_of::() - 4usize]; + ["Offset of field: struct_a::a"][::std::mem::offset_of!(struct_a, a) - 0usize]; +}; +pub type a = *const struct_a; +#[repr(C)] +#[derive(Copy, Clone)] +pub union union_b { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of union_b"][::std::mem::size_of::() - 4usize]; + ["Alignment of union_b"][::std::mem::align_of::() - 4usize]; + ["Offset of field: union_b::a"][::std::mem::offset_of!(union_b, a) - 0usize]; + ["Offset of field: union_b::b"][::std::mem::offset_of!(union_b, b) - 0usize]; +}; +impl Default for union_b { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type b = union_b; +pub const enum_c_A: enum_c = 0; +pub type enum_c = ::std::os::raw::c_uint; +unsafe extern "C" { + pub fn takes_a(arg: a); +} +unsafe extern "C" { + pub fn takes_b(arg: b); +} +unsafe extern "C" { + pub fn takes_c(arg: enum_c); +} diff --git a/bindgen-tests/tests/expectations/tests/call-conv-field.rs b/bindgen-tests/tests/expectations/tests/call-conv-field.rs new file mode 100644 index 0000000000..8f0502a435 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/call-conv-field.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] +#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct JNINativeInterface_ { + pub GetVersion: ::std::option::Option< + unsafe extern "stdcall" fn( + env: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, + >, + pub __hack: ::std::os::raw::c_ulonglong, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of JNINativeInterface_", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of JNINativeInterface_", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: JNINativeInterface_::GetVersion", + ][::std::mem::offset_of!(JNINativeInterface_, GetVersion) - 0usize]; + [ + "Offset of field: JNINativeInterface_::__hack", + ][::std::mem::offset_of!(JNINativeInterface_, __hack) - 8usize]; +}; +unsafe extern "stdcall" { + pub fn bar(); +} diff --git a/bindgen-tests/tests/expectations/tests/call-conv-typedef.rs b/bindgen-tests/tests/expectations/tests/call-conv-typedef.rs new file mode 100644 index 0000000000..c62756f364 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/call-conv-typedef.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] +pub type void_fn = ::std::option::Option; +pub type fn_ = ::std::option::Option< + unsafe extern "stdcall" fn(id: ::std::os::raw::c_int) -> void_fn, +>; diff --git a/bindgen-tests/tests/expectations/tests/canonical-types.rs b/bindgen-tests/tests/expectations/tests/canonical-types.rs new file mode 100644 index 0000000000..81d2e488a2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/canonical-types.rs @@ -0,0 +1,193 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassA { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassA_ClassAInner { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub x: *mut T, +} +impl Default for ClassA_ClassAInner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassB { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassC { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerB { + pub cache: *mut ClassC_ClassCInnerA, +} +impl Default for ClassC_ClassCInnerB { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerA { + pub member: *mut ClassC_ClassCInnerB, +} +impl Default for ClassC_ClassCInnerA { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerCRTP { + pub _address: u8, +} +impl Default for ClassC_ClassCInnerCRTP { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassD { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ClassD"][::std::mem::size_of::() - 1usize]; + ["Alignment of ClassD"][::std::mem::align_of::() - 1usize]; +}; +impl Default for ClassD { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: ClassB_open0_ClassD_ClassCInnerCRTP_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: ClassB_open0_ClassD_ClassCInnerCRTP_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerCRTP { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ClassCInnerCRTP"][::std::mem::size_of::() - 1usize]; + ["Alignment of ClassCInnerCRTP"][::std::mem::align_of::() - 1usize]; +}; +impl Default for ClassCInnerCRTP { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: ClassB_open0_ClassCInnerCRTP_ClassAInner_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: ClassB_open0_ClassCInnerCRTP_ClassAInner_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassAInner { + pub x: *mut ClassCInnerA, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ClassAInner"][::std::mem::size_of::() - 8usize]; + ["Alignment of ClassAInner"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ClassAInner::x"][::std::mem::offset_of!(ClassAInner, x) - 0usize]; +}; +impl Default for ClassAInner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerA { + pub member: *mut ClassCInnerB, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ClassCInnerA"][::std::mem::size_of::() - 8usize]; + ["Alignment of ClassCInnerA"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ClassCInnerA::member", + ][::std::mem::offset_of!(ClassCInnerA, member) - 0usize]; +}; +impl Default for ClassCInnerA { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerB { + pub cache: *mut ClassCInnerA, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ClassCInnerB"][::std::mem::size_of::() - 8usize]; + ["Alignment of ClassCInnerB"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ClassCInnerB::cache", + ][::std::mem::offset_of!(ClassCInnerB, cache) - 0usize]; +}; +impl Default for ClassCInnerB { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/canonical_path_without_namespacing.rs b/bindgen-tests/tests/expectations/tests/canonical_path_without_namespacing.rs new file mode 100644 index 0000000000..613da3060f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/canonical_path_without_namespacing.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_Z3bazPN3foo3BarE"] + pub fn baz(arg1: *mut Bar); +} diff --git a/bindgen-tests/tests/expectations/tests/char.rs b/bindgen-tests/tests/expectations/tests/char.rs new file mode 100644 index 0000000000..61a81269d7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/char.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type Char = ::std::os::raw::c_char; +pub type SChar = ::std::os::raw::c_schar; +pub type UChar = ::std::os::raw::c_uchar; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Test { + pub ch: ::std::os::raw::c_char, + pub u: ::std::os::raw::c_uchar, + pub d: ::std::os::raw::c_schar, + pub cch: ::std::os::raw::c_char, + pub cu: ::std::os::raw::c_uchar, + pub cd: ::std::os::raw::c_schar, + pub Cch: Char, + pub Cu: UChar, + pub Cd: SChar, + pub Ccch: Char, + pub Ccu: UChar, + pub Ccd: SChar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 12usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Test::ch"][::std::mem::offset_of!(Test, ch) - 0usize]; + ["Offset of field: Test::u"][::std::mem::offset_of!(Test, u) - 1usize]; + ["Offset of field: Test::d"][::std::mem::offset_of!(Test, d) - 2usize]; + ["Offset of field: Test::cch"][::std::mem::offset_of!(Test, cch) - 3usize]; + ["Offset of field: Test::cu"][::std::mem::offset_of!(Test, cu) - 4usize]; + ["Offset of field: Test::cd"][::std::mem::offset_of!(Test, cd) - 5usize]; + ["Offset of field: Test::Cch"][::std::mem::offset_of!(Test, Cch) - 6usize]; + ["Offset of field: Test::Cu"][::std::mem::offset_of!(Test, Cu) - 7usize]; + ["Offset of field: Test::Cd"][::std::mem::offset_of!(Test, Cd) - 8usize]; + ["Offset of field: Test::Ccch"][::std::mem::offset_of!(Test, Ccch) - 9usize]; + ["Offset of field: Test::Ccu"][::std::mem::offset_of!(Test, Ccu) - 10usize]; + ["Offset of field: Test::Ccd"][::std::mem::offset_of!(Test, Ccd) - 11usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/char16_t.rs b/bindgen-tests/tests/expectations/tests/char16_t.rs new file mode 100644 index 0000000000..82d30fe517 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/char16_t.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(transparent)] +pub struct bindgen_cchar16_t(u16); +unsafe extern "C" { + #[link_name = "\u{1}_Z16receive_char16_tDs"] + pub fn receive_char16_t(input: bindgen_cchar16_t); +} diff --git a/bindgen-tests/tests/expectations/tests/class.rs b/bindgen-tests/tests/expectations/tests/class.rs new file mode 100644 index 0000000000..98ee43b374 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class.rs @@ -0,0 +1,377 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct C { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 40usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::a"][::std::mem::offset_of!(C, a) - 0usize]; + ["Offset of field: C::big_array"][::std::mem::offset_of!(C, big_array) - 4usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug)] +pub struct C_with_zero_length_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_zero_length_array", + ][::std::mem::size_of::() - 40usize]; + [ + "Alignment of C_with_zero_length_array", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_with_zero_length_array::a", + ][::std::mem::offset_of!(C_with_zero_length_array, a) - 0usize]; + [ + "Offset of field: C_with_zero_length_array::big_array", + ][::std::mem::offset_of!(C_with_zero_length_array, big_array) - 4usize]; + [ + "Offset of field: C_with_zero_length_array::zero_length_array", + ][::std::mem::offset_of!(C_with_zero_length_array, zero_length_array) - 37usize]; +}; +impl Default for C_with_zero_length_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_zero_length_array_2 { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_zero_length_array_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of C_with_zero_length_array_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_with_zero_length_array_2::a", + ][::std::mem::offset_of!(C_with_zero_length_array_2, a) - 0usize]; + [ + "Offset of field: C_with_zero_length_array_2::zero_length_array", + ][::std::mem::offset_of!(C_with_zero_length_array_2, zero_length_array) - 4usize]; +}; +#[repr(C)] +#[derive(Debug)] +pub struct C_with_incomplete_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_incomplete_array", + ][::std::mem::size_of::() - 40usize]; + [ + "Alignment of C_with_incomplete_array", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_with_incomplete_array::a", + ][::std::mem::offset_of!(C_with_incomplete_array, a) - 0usize]; + [ + "Offset of field: C_with_incomplete_array::big_array", + ][::std::mem::offset_of!(C_with_incomplete_array, big_array) - 4usize]; + [ + "Offset of field: C_with_incomplete_array::incomplete_array", + ][::std::mem::offset_of!(C_with_incomplete_array, incomplete_array) - 37usize]; +}; +impl Default for C_with_incomplete_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_incomplete_array_2 { + pub a: ::std::os::raw::c_int, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_incomplete_array_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of C_with_incomplete_array_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_with_incomplete_array_2::a", + ][::std::mem::offset_of!(C_with_incomplete_array_2, a) - 0usize]; + [ + "Offset of field: C_with_incomplete_array_2::incomplete_array", + ][::std::mem::offset_of!(C_with_incomplete_array_2, incomplete_array) - 4usize]; +}; +#[repr(C)] +#[derive(Debug)] +pub struct C_with_zero_length_array_and_incomplete_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_zero_length_array_and_incomplete_array", + ][::std::mem::size_of::() - 40usize]; + [ + "Alignment of C_with_zero_length_array_and_incomplete_array", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array::a", + ][::std::mem::offset_of!(C_with_zero_length_array_and_incomplete_array, a) - 0usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array::big_array", + ][::std::mem::offset_of!(C_with_zero_length_array_and_incomplete_array, big_array) + - 4usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array::zero_length_array", + ][::std::mem::offset_of!( + C_with_zero_length_array_and_incomplete_array, zero_length_array + ) - 37usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array::incomplete_array", + ][::std::mem::offset_of!( + C_with_zero_length_array_and_incomplete_array, incomplete_array + ) - 37usize]; +}; +impl Default for C_with_zero_length_array_and_incomplete_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_zero_length_array_and_incomplete_array_2 { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C_with_zero_length_array_and_incomplete_array_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of C_with_zero_length_array_and_incomplete_array_2", + ][::std::mem::align_of::() + - 4usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array_2::a", + ][::std::mem::offset_of!(C_with_zero_length_array_and_incomplete_array_2, a) + - 0usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array_2::zero_length_array", + ][::std::mem::offset_of!( + C_with_zero_length_array_and_incomplete_array_2, zero_length_array + ) - 4usize]; + [ + "Offset of field: C_with_zero_length_array_and_incomplete_array_2::incomplete_array", + ][::std::mem::offset_of!( + C_with_zero_length_array_and_incomplete_array_2, incomplete_array + ) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct WithDtor { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithDtor"][::std::mem::size_of::() - 4usize]; + ["Alignment of WithDtor"][::std::mem::align_of::() - 4usize]; + ["Offset of field: WithDtor::b"][::std::mem::offset_of!(WithDtor, b) - 0usize]; +}; +#[repr(C)] +#[derive(Debug)] +pub struct IncompleteArrayNonCopiable { + pub whatever: *mut ::std::os::raw::c_void, + pub incomplete_array: __IncompleteArrayField, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of IncompleteArrayNonCopiable", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of IncompleteArrayNonCopiable", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: IncompleteArrayNonCopiable::whatever", + ][::std::mem::offset_of!(IncompleteArrayNonCopiable, whatever) - 0usize]; + [ + "Offset of field: IncompleteArrayNonCopiable::incomplete_array", + ][::std::mem::offset_of!(IncompleteArrayNonCopiable, incomplete_array) - 8usize]; +}; +impl Default for IncompleteArrayNonCopiable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union Union { + pub d: f32, + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Union"][::std::mem::size_of::() - 4usize]; + ["Alignment of Union"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Union::d"][::std::mem::offset_of!(Union, d) - 0usize]; + ["Offset of field: Union::i"][::std::mem::offset_of!(Union, i) - 0usize]; +}; +impl Default for Union { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct WithUnion { + pub data: Union, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithUnion"][::std::mem::size_of::() - 4usize]; + ["Alignment of WithUnion"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithUnion::data", + ][::std::mem::offset_of!(WithUnion, data) - 0usize]; +}; +impl Default for WithUnion { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct RealAbstractionWithTonsOfMethods { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of RealAbstractionWithTonsOfMethods", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of RealAbstractionWithTonsOfMethods", + ][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZNK32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar( + this: *const RealAbstractionWithTonsOfMethods, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar1( + this: *mut RealAbstractionWithTonsOfMethods, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEi"] + pub fn RealAbstractionWithTonsOfMethods_bar2( + this: *mut RealAbstractionWithTonsOfMethods, + foo: ::std::os::raw::c_int, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3staEv"] + pub fn RealAbstractionWithTonsOfMethods_sta(); +} +impl RealAbstractionWithTonsOfMethods { + #[inline] + pub unsafe fn bar(&self) { + RealAbstractionWithTonsOfMethods_bar(self) + } + #[inline] + pub unsafe fn bar1(&mut self) { + RealAbstractionWithTonsOfMethods_bar1(self) + } + #[inline] + pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { + RealAbstractionWithTonsOfMethods_bar2(self, foo) + } + #[inline] + pub unsafe fn sta() { + RealAbstractionWithTonsOfMethods_sta() + } +} diff --git a/bindgen-tests/tests/expectations/tests/class_nested.rs b/bindgen-tests/tests/expectations/tests/class_nested.rs new file mode 100644 index 0000000000..080f5968bc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_nested.rs @@ -0,0 +1,105 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A { + pub member_a: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A_B { + pub member_b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A_B"][::std::mem::size_of::() - 4usize]; + ["Alignment of A_B"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A_B::member_b"][::std::mem::offset_of!(A_B, member_b) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A_D { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub foo: T, +} +impl Default for A_D { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 4usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::member_a"][::std::mem::offset_of!(A, member_a) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A_C { + pub baz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A_C"][::std::mem::size_of::() - 4usize]; + ["Alignment of A_C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A_C::baz"][::std::mem::offset_of!(A_C, baz) - 0usize]; +}; +unsafe extern "C" { + pub static mut var: A_B; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: A_D_open0_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: A_D_open0_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +unsafe extern "C" { + pub static mut baz: A_D<::std::os::raw::c_int>; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct D { + pub member: A_B, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of D"][::std::mem::size_of::() - 4usize]; + ["Alignment of D"][::std::mem::align_of::() - 4usize]; + ["Offset of field: D::member"][::std::mem::offset_of!(D, member) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Templated { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Templated_Templated_inner { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member_ptr: *mut T, +} +impl Default for Templated_Templated_inner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for Templated { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/class_no_members.rs b/bindgen-tests/tests/expectations/tests/class_no_members.rs new file mode 100644 index 0000000000..c50da6a02d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_no_members.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct whatever { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of whatever"][::std::mem::size_of::() - 1usize]; + ["Alignment of whatever"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct whatever_child { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of whatever_child"][::std::mem::size_of::() - 1usize]; + ["Alignment of whatever_child"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct whatever_child_with_member { + pub m_member: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of whatever_child_with_member", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of whatever_child_with_member", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: whatever_child_with_member::m_member", + ][::std::mem::offset_of!(whatever_child_with_member, m_member) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/class_static.rs b/bindgen-tests/tests/expectations/tests/class_static.rs new file mode 100644 index 0000000000..d448165d62 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_static.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct MyClass { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN7MyClass7exampleE"] + pub static mut MyClass_example: *const ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN7MyClass26example_check_no_collisionE"] + pub static mut MyClass_example_check_no_collision: *const ::std::os::raw::c_int; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of MyClass"][::std::mem::size_of::() - 1usize]; + ["Alignment of MyClass"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZL26example_check_no_collision"] + pub static mut example_check_no_collision: *const ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/class_static_const.rs b/bindgen-tests/tests/expectations/tests/class_static_const.rs new file mode 100644 index 0000000000..d628239c4c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_static_const.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A { + pub _address: u8, +} +pub const A_a: ::std::os::raw::c_int = 0; +pub const A_b: i32 = 63; +pub const A_c: u32 = 255; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/class_use_as.rs b/bindgen-tests/tests/expectations/tests/class_use_as.rs new file mode 100644 index 0000000000..ec898ff7eb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_use_as.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct whatever { + pub replacement: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of whatever"][::std::mem::size_of::() - 4usize]; + ["Alignment of whatever"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: whatever::replacement", + ][::std::mem::offset_of!(whatever, replacement) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct container { + pub c: whatever, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of container"][::std::mem::size_of::() - 4usize]; + ["Alignment of container"][::std::mem::align_of::() - 4usize]; + ["Offset of field: container::c"][::std::mem::offset_of!(container, c) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/class_with_dtor.rs b/bindgen-tests/tests/expectations/tests/class_with_dtor.rs new file mode 100644 index 0000000000..aa99f42468 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_with_dtor.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct HandleWithDtor { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: *mut T, +} +impl Default for HandleWithDtor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct WithoutDtor { + pub shouldBeWithDtor: HandleValue, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithoutDtor"][::std::mem::size_of::() - 8usize]; + ["Alignment of WithoutDtor"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: WithoutDtor::shouldBeWithDtor", + ][::std::mem::offset_of!(WithoutDtor, shouldBeWithDtor) - 0usize]; +}; +impl Default for WithoutDtor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: HandleWithDtor_open0_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: HandleWithDtor_open0_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/class_with_enum.rs b/bindgen-tests/tests/expectations/tests/class_with_enum.rs new file mode 100644 index 0000000000..ca1806357c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_with_enum.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +pub const A_B_B1: A_B = 0; +pub const A_B_B2: A_B = 1; +pub type A_B = ::std::os::raw::c_uint; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::
() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/class_with_inner_struct.rs b/bindgen-tests/tests/expectations/tests/class_with_inner_struct.rs new file mode 100644 index 0000000000..710026c72f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_with_inner_struct.rs @@ -0,0 +1,235 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct A { + pub c: ::std::os::raw::c_uint, + pub named_union: A__bindgen_ty_1, + pub __bindgen_anon_1: A__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct A_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A_Segment"][::std::mem::size_of::() - 8usize]; + ["Alignment of A_Segment"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: A_Segment::begin", + ][::std::mem::offset_of!(A_Segment, begin) - 0usize]; + ["Offset of field: A_Segment::end"][::std::mem::offset_of!(A_Segment, end) - 4usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub union A__bindgen_ty_1 { + pub f: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + ["Alignment of A__bindgen_ty_1"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: A__bindgen_ty_1::f", + ][::std::mem::offset_of!(A__bindgen_ty_1, f) - 0usize]; +}; +impl Default for A__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union A__bindgen_ty_2 { + pub d: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A__bindgen_ty_2"][::std::mem::size_of::() - 4usize]; + ["Alignment of A__bindgen_ty_2"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: A__bindgen_ty_2::d", + ][::std::mem::offset_of!(A__bindgen_ty_2, d) - 0usize]; +}; +impl Default for A__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 12usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::c"][::std::mem::offset_of!(A, c) - 0usize]; + ["Offset of field: A::named_union"][::std::mem::offset_of!(A, named_union) - 4usize]; +}; +impl Default for A { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct B { + pub d: ::std::os::raw::c_uint, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct B_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B_Segment"][::std::mem::size_of::() - 8usize]; + ["Alignment of B_Segment"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: B_Segment::begin", + ][::std::mem::offset_of!(B_Segment, begin) - 0usize]; + ["Offset of field: B_Segment::end"][::std::mem::offset_of!(B_Segment, end) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 4usize]; + ["Alignment of B"][::std::mem::align_of::() - 4usize]; + ["Offset of field: B::d"][::std::mem::offset_of!(B, d) - 0usize]; +}; +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum StepSyntax { + Keyword = 0, + FunctionalWithoutKeyword = 1, + FunctionalWithStartKeyword = 2, + FunctionalWithEndKeyword = 3, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct C { + pub d: ::std::os::raw::c_uint, + pub __bindgen_anon_1: C__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union C__bindgen_ty_1 { + pub mFunc: C__bindgen_ty_1__bindgen_ty_1, + pub __bindgen_anon_1: C__bindgen_ty_1__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct C__bindgen_ty_1__bindgen_ty_1 { + pub mX1: f32, + pub mY1: f32, + pub mX2: f32, + pub mY2: f32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of C__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_1::mX1", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_1, mX1) - 0usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_1::mY1", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_1, mY1) - 4usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_1::mX2", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_1, mX2) - 8usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_1::mY2", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_1, mY2) - 12usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct C__bindgen_ty_1__bindgen_ty_2 { + pub mStepSyntax: StepSyntax, + pub mSteps: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of C__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of C__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_2::mStepSyntax", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_2, mStepSyntax) - 0usize]; + [ + "Offset of field: C__bindgen_ty_1__bindgen_ty_2::mSteps", + ][::std::mem::offset_of!(C__bindgen_ty_1__bindgen_ty_2, mSteps) - 4usize]; +}; +impl Default for C__bindgen_ty_1__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C__bindgen_ty_1"][::std::mem::size_of::() - 16usize]; + ["Alignment of C__bindgen_ty_1"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C__bindgen_ty_1::mFunc", + ][::std::mem::offset_of!(C__bindgen_ty_1, mFunc) - 0usize]; +}; +impl Default for C__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct C_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C_Segment"][::std::mem::size_of::() - 8usize]; + ["Alignment of C_Segment"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: C_Segment::begin", + ][::std::mem::offset_of!(C_Segment, begin) - 0usize]; + ["Offset of field: C_Segment::end"][::std::mem::offset_of!(C_Segment, end) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 20usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::d"][::std::mem::offset_of!(C, d) - 0usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/class_with_typedef.rs b/bindgen-tests/tests/expectations/tests/class_with_typedef.rs new file mode 100644 index 0000000000..73f2b55cc3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/class_with_typedef.rs @@ -0,0 +1,87 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type AnotherInt = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct C { + pub c: C_MyInt, + pub ptr: *mut C_MyInt, + pub arr: [C_MyInt; 10usize], + pub d: AnotherInt, + pub other_ptr: *mut AnotherInt, +} +pub type C_MyInt = ::std::os::raw::c_int; +pub type C_Lookup = *const ::std::os::raw::c_char; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 72usize]; + ["Alignment of C"][::std::mem::align_of::() - 8usize]; + ["Offset of field: C::c"][::std::mem::offset_of!(C, c) - 0usize]; + ["Offset of field: C::ptr"][::std::mem::offset_of!(C, ptr) - 8usize]; + ["Offset of field: C::arr"][::std::mem::offset_of!(C, arr) - 16usize]; + ["Offset of field: C::d"][::std::mem::offset_of!(C, d) - 56usize]; + ["Offset of field: C::other_ptr"][::std::mem::offset_of!(C, other_ptr) - 64usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C6methodEi"] + pub fn C_method(this: *mut C, c: C_MyInt); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C9methodRefERi"] + pub fn C_methodRef(this: *mut C, c: *mut C_MyInt); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C16complexMethodRefERPKc"] + pub fn C_complexMethodRef(this: *mut C, c: *mut C_Lookup); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C13anotherMethodEi"] + pub fn C_anotherMethod(this: *mut C, c: AnotherInt); +} +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl C { + #[inline] + pub unsafe fn method(&mut self, c: C_MyInt) { + C_method(self, c) + } + #[inline] + pub unsafe fn methodRef(&mut self, c: *mut C_MyInt) { + C_methodRef(self, c) + } + #[inline] + pub unsafe fn complexMethodRef(&mut self, c: *mut C_Lookup) { + C_complexMethodRef(self, c) + } + #[inline] + pub unsafe fn anotherMethod(&mut self, c: AnotherInt) { + C_anotherMethod(self, c) + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct D { + pub _base: C, + pub ptr: *mut C_MyInt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of D"][::std::mem::size_of::() - 80usize]; + ["Alignment of D"][::std::mem::align_of::() - 8usize]; + ["Offset of field: D::ptr"][::std::mem::offset_of!(D, ptr) - 72usize]; +}; +impl Default for D { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/comment-indent.rs b/bindgen-tests/tests/expectations/tests/comment-indent.rs new file mode 100644 index 0000000000..72b167d00c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/comment-indent.rs @@ -0,0 +1,81 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + /** This is a multi-line doc comment. + + This class is really really interesting, look!*/ + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Foo { + pub _address: u8, + } + /** This nested class is also a multi-line doc comment. + + This class is not so interesting, but worth a bit of docs too!*/ + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Foo_Bar { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Foo_Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo_Bar"][::std::mem::align_of::() - 1usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; + }; + pub mod test { + #[allow(unused_imports)] + use self::super::super::root; + /** I'm in a namespace, and thus I may be on a rust module, most of the time. + My documentation is pretty extensive, I guess.*/ + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Baz { + /** This member is plain awesome, just amazing. + + It also has super-extensive docs, with even a nice ascii-art diagram. + + +------+ +-------+ + | foo | ----> | bar | + +------+ +-------+*/ + pub member: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Baz::member", + ][::std::mem::offset_of!(Baz, member) - 0usize]; + }; + /** I'm in an inline namespace, and as such I shouldn't get generated inside + a rust module, except when the relevant option is specified. Also, this + comment shouldn't be misaligned.*/ + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct InInlineNS { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of InInlineNS"][::std::mem::size_of::() - 1usize]; + ["Alignment of InInlineNS"][::std::mem::align_of::() - 1usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bazz { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bazz"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bazz"][::std::mem::align_of::() - 1usize]; + }; + } +} diff --git a/bindgen-tests/tests/expectations/tests/complex.rs b/bindgen-tests/tests/expectations/tests/complex.rs new file mode 100644 index 0000000000..233b86ea36 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/complex.rs @@ -0,0 +1,77 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct TestDouble { + pub mMember: __BindgenComplex, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestDouble"][::std::mem::size_of::() - 16usize]; + ["Alignment of TestDouble"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: TestDouble::mMember", + ][::std::mem::offset_of!(TestDouble, mMember) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct TestDoublePtr { + pub mMember: *mut __BindgenComplex, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestDoublePtr"][::std::mem::size_of::() - 8usize]; + ["Alignment of TestDoublePtr"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: TestDoublePtr::mMember", + ][::std::mem::offset_of!(TestDoublePtr, mMember) - 0usize]; +}; +impl Default for TestDoublePtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct TestFloat { + pub mMember: __BindgenComplex, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestFloat"][::std::mem::size_of::() - 8usize]; + ["Alignment of TestFloat"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: TestFloat::mMember", + ][::std::mem::offset_of!(TestFloat, mMember) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct TestFloatPtr { + pub mMember: *mut __BindgenComplex, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestFloatPtr"][::std::mem::size_of::() - 8usize]; + ["Alignment of TestFloatPtr"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: TestFloatPtr::mMember", + ][::std::mem::offset_of!(TestFloatPtr, mMember) - 0usize]; +}; +impl Default for TestFloatPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/complex_global.rs b/bindgen-tests/tests/expectations/tests/complex_global.rs new file mode 100644 index 0000000000..c818df676e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/complex_global.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +unsafe extern "C" { + pub static mut globalValueFloat: __BindgenComplex; +} +unsafe extern "C" { + pub static mut globalValueDouble: __BindgenComplex; +} +unsafe extern "C" { + pub static mut globalValueLongDouble: __BindgenComplex; +} diff --git a/bindgen-tests/tests/expectations/tests/const-const-mut-ptr.rs b/bindgen-tests/tests/expectations/tests/const-const-mut-ptr.rs new file mode 100644 index 0000000000..72a34da105 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const-const-mut-ptr.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub bar: *const *const *mut *const ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/const_array.rs b/bindgen-tests/tests/expectations/tests/const_array.rs new file mode 100644 index 0000000000..30852deb36 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_array.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static foo: [::std::os::raw::c_int; 1usize]; +} +unsafe extern "C" { + pub static mut bar: [::std::os::raw::c_int; 1usize]; +} diff --git a/bindgen-tests/tests/expectations/tests/const_array_fn_arg.rs b/bindgen-tests/tests/expectations/tests/const_array_fn_arg.rs new file mode 100644 index 0000000000..fb26311115 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_array_fn_arg.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn f(a: *const ::std::os::raw::c_int); +} diff --git a/bindgen-tests/tests/expectations/tests/const_array_typedef.rs b/bindgen-tests/tests/expectations/tests/const_array_typedef.rs new file mode 100644 index 0000000000..034856d359 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_array_typedef.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct strct { + pub field: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of strct"][::std::mem::size_of::() - 4usize]; + ["Alignment of strct"][::std::mem::align_of::() - 4usize]; + ["Offset of field: strct::field"][::std::mem::offset_of!(strct, field) - 0usize]; +}; +pub type typ = [strct; 1usize]; +unsafe extern "C" { + pub static mut w: typ; +} +unsafe extern "C" { + pub static mut x: *mut strct; +} +unsafe extern "C" { + pub static y: typ; +} +unsafe extern "C" { + pub static mut z: *const strct; +} +unsafe extern "C" { + pub fn function(a: *const strct, b: *const strct); +} diff --git a/bindgen-tests/tests/expectations/tests/const_bool.rs b/bindgen-tests/tests/expectations/tests/const_bool.rs new file mode 100644 index 0000000000..2cbab47390 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_bool.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const k: bool = true; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +pub const A_k: bool = false; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; +pub type foo = bool; +pub const k2: foo = true; diff --git a/bindgen-tests/tests/expectations/tests/const_enum_unnamed.rs b/bindgen-tests/tests/expectations/tests/const_enum_unnamed.rs new file mode 100644 index 0000000000..f49d825224 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_enum_unnamed.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR; +pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + FOO_BAR = 0, + FOO_BAZ = 1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo__bindgen_ty_1 { + FOO_BAR = 10, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/const_multidim_array_fn_arg.rs b/bindgen-tests/tests/expectations/tests/const_multidim_array_fn_arg.rs new file mode 100644 index 0000000000..db0ce114fb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_multidim_array_fn_arg.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn f(a: *const [::std::os::raw::c_int; 1usize]); +} diff --git a/bindgen-tests/tests/expectations/tests/const_ptr.rs b/bindgen-tests/tests/expectations/tests/const_ptr.rs new file mode 100644 index 0000000000..9b9e38c1e7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_ptr.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(bar: *const ::std::os::raw::c_void); +} diff --git a/bindgen-tests/tests/expectations/tests/const_resolved_ty.rs b/bindgen-tests/tests/expectations/tests/const_resolved_ty.rs new file mode 100644 index 0000000000..ed49b69f64 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_resolved_ty.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(foo: *const u8); +} diff --git a/bindgen-tests/tests/expectations/tests/const_tparam.rs b/bindgen-tests/tests/expectations/tests/const_tparam.rs new file mode 100644 index 0000000000..c6b16a8959 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/const_tparam.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub foo: *const T, + pub bar: *const T, +} +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constant-evaluate.rs b/bindgen-tests/tests/expectations/tests/constant-evaluate.rs new file mode 100644 index 0000000000..bbcf6d5450 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constant-evaluate.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; +pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + foo = 4, + bar = 8, +} +pub type EasyToOverflow = ::std::os::raw::c_ulonglong; +pub const k: EasyToOverflow = 2147483648; +pub const k_expr: EasyToOverflow = 1152921504606846976; +pub const wow: EasyToOverflow = 2147483648; +pub const BAZ: ::std::os::raw::c_longlong = 24; +pub const fuzz: f64 = 51.0; +pub const BAZZ: ::std::os::raw::c_char = 53; +pub const WAT: ::std::os::raw::c_char = 0; +pub const bytestring: &[u8; 4] = b"Foo\0"; +pub const NOT_UTF8: &[u8; 5] = b"\xF0(\x8C(\0"; diff --git a/tests/expectations/tests/constant-non-specialized-tp.rs b/bindgen-tests/tests/expectations/tests/constant-non-specialized-tp.rs similarity index 88% rename from tests/expectations/tests/constant-non-specialized-tp.rs rename to bindgen-tests/tests/expectations/tests/constant-non-specialized-tp.rs index 8be8e5d3b2..968ec350aa 100644 --- a/tests/expectations/tests/constant-non-specialized-tp.rs +++ b/bindgen-tests/tests/expectations/tests/constant-non-specialized-tp.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Test { diff --git a/bindgen-tests/tests/expectations/tests/constified-enum-module-overflow.rs b/bindgen-tests/tests/expectations/tests/constified-enum-module-overflow.rs new file mode 100644 index 0000000000..e5eada9abc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constified-enum-module-overflow.rs @@ -0,0 +1,41 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct B { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub _address: u8, +} +pub type C_U = B; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub u: B, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; + ["Offset of field: A::u"][::std::mem::offset_of!(A, u) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: C_open0_A_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: C_open0_A_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_A_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: B_open0_A_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/constify-all-enums.rs b/bindgen-tests/tests/expectations/tests/constify-all-enums.rs new file mode 100644 index 0000000000..7913454b56 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-all-enums.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const foo_THIS: foo = 0; +pub const foo_SHOULD_BE: foo = 1; +pub const foo_A_CONSTANT: foo = 2; +pub type foo = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bar { + pub this_should_work: foo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: bar::this_should_work", + ][::std::mem::offset_of!(bar, this_should_work) - 0usize]; +}; +impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constify-enum.rs b/bindgen-tests/tests/expectations/tests/constify-enum.rs new file mode 100644 index 0000000000..67d2749c51 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-enum.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const nsCSSPropertyID_eCSSProperty_COUNT_unexistingVariantValue: nsCSSPropertyID = nsCSSPropertyID::eCSSProperty_COUNT_unexistingVariantValue; +impl nsCSSPropertyID { + pub const eCSSProperty_COUNT: nsCSSPropertyID = nsCSSPropertyID::eCSSPropertyAlias_aa; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum nsCSSPropertyID { + eCSSProperty_a = 0, + eCSSProperty_b = 1, + eCSSPropertyAlias_aa = 2, + eCSSPropertyAlias_bb = 3, + ///<
+ eCSSProperty_COUNT_unexistingVariantValue = 4, +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-basic.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-basic.rs new file mode 100644 index 0000000000..aad696d074 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-basic.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; +} +pub use self::foo::Type as foo_alias1; +pub use self::foo_alias1 as foo_alias2; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bar { + pub this_should_work: foo::Type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: bar::this_should_work", + ][::std::mem::offset_of!(bar, this_should_work) - 0usize]; +}; +impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + pub fn func1( + arg1: foo::Type, + arg2: *mut foo::Type, + arg3: *mut *mut foo::Type, + ) -> *mut foo::Type; +} +unsafe extern "C" { + pub fn func2( + arg1: foo_alias1, + arg2: *mut foo_alias1, + arg3: *mut *mut foo_alias1, + ) -> *mut foo_alias1; +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-namespace.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-namespace.rs new file mode 100644 index 0000000000..cdf6e7ebb4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-namespace.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod ns1 { + #[allow(unused_imports)] + use self::super::super::root; + pub mod ns2 { + #[allow(unused_imports)] + use self::super::super::super::root; + pub mod foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + } + } + pub mod ns3 { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct bar { + pub this_should_work: root::ns1::ns2::foo::Type, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: bar::this_should_work", + ][::std::mem::offset_of!(bar, this_should_work) - 0usize]; + }; + impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-shadow-name.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-shadow-name.rs new file mode 100644 index 0000000000..987f4463a2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-shadow-name.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const Type: Type = 0; + pub const Type_: Type = 1; + pub const Type1: Type = 2; + pub const Type__: Type = 3; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bar { + pub member: foo::Type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar::member"][::std::mem::offset_of!(bar, member) - 0usize]; +}; +impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-alias.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-alias.rs new file mode 100644 index 0000000000..5f7b9ede4a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-alias.rs @@ -0,0 +1,46 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; + pub const Variant3: Type = 2; +} +pub use self::Foo::Type as Foo_alias1; +pub use self::Foo_alias1 as Foo_alias2; +pub use self::Foo_alias2 as Foo_alias3; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub baz1: Foo::Type, + pub baz2: Foo_alias1, + pub baz3: Foo_alias2, + pub baz4: Foo_alias3, + pub baz_ptr1: *mut Foo::Type, + pub baz_ptr2: *mut Foo_alias1, + pub baz_ptr3: *mut Foo_alias2, + pub baz_ptr4: *mut Foo_alias3, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 48usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::baz1"][::std::mem::offset_of!(Bar, baz1) - 0usize]; + ["Offset of field: Bar::baz2"][::std::mem::offset_of!(Bar, baz2) - 4usize]; + ["Offset of field: Bar::baz3"][::std::mem::offset_of!(Bar, baz3) - 8usize]; + ["Offset of field: Bar::baz4"][::std::mem::offset_of!(Bar, baz4) - 12usize]; + ["Offset of field: Bar::baz_ptr1"][::std::mem::offset_of!(Bar, baz_ptr1) - 16usize]; + ["Offset of field: Bar::baz_ptr2"][::std::mem::offset_of!(Bar, baz_ptr2) - 24usize]; + ["Offset of field: Bar::baz_ptr3"][::std::mem::offset_of!(Bar, baz_ptr3) - 32usize]; + ["Offset of field: Bar::baz_ptr4"][::std::mem::offset_of!(Bar, baz_ptr4) - 40usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs new file mode 100644 index 0000000000..dc59f5fc1d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod one_Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub baz1: one_Foo::Type, + pub baz2: *mut one_Foo::Type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 16usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::baz1"][::std::mem::offset_of!(Bar, baz1) - 0usize]; + ["Offset of field: Bar::baz2"][::std::mem::offset_of!(Bar, baz2) - 8usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/constify-module-enums-types.rs b/bindgen-tests/tests/expectations/tests/constify-module-enums-types.rs new file mode 100644 index 0000000000..a4a69fd72d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constify-module-enums-types.rs @@ -0,0 +1,173 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type Uint = ::std::os::raw::c_uint; +pub mod ExplicitTypeAlias { + #[allow(unused_imports)] + use super::*; + pub type Type = Uint; + pub const SOME_CONSTANT: Type = 0; + pub const SOME_OTHER_CONSTANT: Type = 1; +} +pub mod foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + pub const ALSO_THIS: Type = 42; + pub const AND_ALSO_THIS: Type = 42; +} +pub mod anon_enum { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; + pub const Variant3: Type = 2; +} +pub mod ns1_foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + pub const ALSO_THIS: Type = 42; +} +pub mod ns2_Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +pub use self::foo::Type as foo_alias1; +pub use self::foo_alias1 as foo_alias2; +pub use self::foo_alias2 as foo_alias3; +pub use self::anon_enum::Type as anon_enum_alias1; +pub use self::anon_enum_alias1 as anon_enum_alias2; +pub use self::anon_enum_alias2 as anon_enum_alias3; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bar { + pub member1: foo::Type, + pub member2: foo_alias1, + pub member3: foo_alias2, + pub member4: foo_alias3, + pub member5: ns1_foo::Type, + pub member6: *mut ns2_Foo::Type, + pub member7: anon_enum::Type, + pub member8: anon_enum_alias1, + pub member9: anon_enum_alias2, + pub member10: anon_enum_alias3, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 48usize]; + ["Alignment of bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: bar::member1"][::std::mem::offset_of!(bar, member1) - 0usize]; + ["Offset of field: bar::member2"][::std::mem::offset_of!(bar, member2) - 4usize]; + ["Offset of field: bar::member3"][::std::mem::offset_of!(bar, member3) - 8usize]; + ["Offset of field: bar::member4"][::std::mem::offset_of!(bar, member4) - 12usize]; + ["Offset of field: bar::member5"][::std::mem::offset_of!(bar, member5) - 16usize]; + ["Offset of field: bar::member6"][::std::mem::offset_of!(bar, member6) - 24usize]; + ["Offset of field: bar::member7"][::std::mem::offset_of!(bar, member7) - 32usize]; + ["Offset of field: bar::member8"][::std::mem::offset_of!(bar, member8) - 36usize]; + ["Offset of field: bar::member9"][::std::mem::offset_of!(bar, member9) - 40usize]; + ["Offset of field: bar::member10"][::std::mem::offset_of!(bar, member10) - 44usize]; +}; +impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Baz { + pub member1: ns2_Foo::Type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Baz::member1"][::std::mem::offset_of!(Baz, member1) - 0usize]; +}; +impl Default for Baz { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub mod one_Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub baz: *mut one_Foo::Type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::baz"][::std::mem::offset_of!(Bar, baz) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z5func13fooPS_PS0_"] + pub fn func1( + arg1: foo::Type, + arg2: *mut foo::Type, + arg3: *mut *mut foo::Type, + ) -> *mut foo::Type; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z5func23fooPS_PS0_"] + pub fn func2( + arg1: foo_alias1, + arg2: *mut foo_alias1, + arg3: *mut *mut foo_alias1, + ) -> *mut foo_alias1; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Thing { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub thing: T, +} +impl Default for Thing { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z5func35ThingI3fooE"] + pub fn func3(arg1: Thing) -> foo::Type; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z5func45ThingIS_I3fooEE"] + pub fn func4(arg1: Thing>) -> foo::Type; +} diff --git a/bindgen-tests/tests/expectations/tests/constructor-tp.rs b/bindgen-tests/tests/expectations/tests/constructor-tp.rs new file mode 100644 index 0000000000..2585311d29 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constructor-tp.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3BarC1Ev"] + pub fn Bar_Bar(this: *mut Bar); +} +impl Bar { + #[inline] + pub unsafe fn new() -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + Bar_Bar(__bindgen_tmp.as_mut_ptr()); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/constructors.rs b/bindgen-tests/tests/expectations/tests/constructors.rs new file mode 100644 index 0000000000..45c29e61e5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constructors.rs @@ -0,0 +1,60 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct TestOverload { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestOverload"][::std::mem::size_of::() - 1usize]; + ["Alignment of TestOverload"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN12TestOverloadC1Ei"] + pub fn TestOverload_TestOverload( + this: *mut TestOverload, + arg1: ::std::os::raw::c_int, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN12TestOverloadC1Ed"] + pub fn TestOverload_TestOverload1(this: *mut TestOverload, arg1: f64); +} +impl TestOverload { + #[inline] + pub unsafe fn new(arg1: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestOverload_TestOverload(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn new1(arg1: f64) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestOverload_TestOverload1(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct TestPublicNoArgs { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestPublicNoArgs"][::std::mem::size_of::() - 1usize]; + [ + "Alignment of TestPublicNoArgs", + ][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN16TestPublicNoArgsC1Ev"] + pub fn TestPublicNoArgs_TestPublicNoArgs(this: *mut TestPublicNoArgs); +} +impl TestPublicNoArgs { + #[inline] + pub unsafe fn new() -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestPublicNoArgs_TestPublicNoArgs(__bindgen_tmp.as_mut_ptr()); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/constructors_1_33.rs b/bindgen-tests/tests/expectations/tests/constructors_1_33.rs new file mode 100644 index 0000000000..5dbda00007 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/constructors_1_33.rs @@ -0,0 +1,62 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct TestOverload { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestOverload"][::std::mem::size_of::() - 1usize]; + ["Alignment of TestOverload"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + /// Calling this should use `mem::unintialized()` and not `MaybeUninit()` as only rust 1.36 includes that. + #[link_name = "\u{1}_ZN12TestOverloadC1Ei"] + pub fn TestOverload_TestOverload( + this: *mut TestOverload, + arg1: ::std::os::raw::c_int, + ); +} +unsafe extern "C" { + /// Calling this should use `mem::unintialized()` and not `MaybeUninit()` as only rust 1.36 includes that. + #[link_name = "\u{1}_ZN12TestOverloadC1Ed"] + pub fn TestOverload_TestOverload1(this: *mut TestOverload, arg1: f64); +} +impl TestOverload { + #[inline] + pub unsafe fn new(arg1: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestOverload_TestOverload(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn new1(arg1: f64) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestOverload_TestOverload1(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct TestPublicNoArgs { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TestPublicNoArgs"][::std::mem::size_of::() - 1usize]; + [ + "Alignment of TestPublicNoArgs", + ][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN16TestPublicNoArgsC1Ev"] + pub fn TestPublicNoArgs_TestPublicNoArgs(this: *mut TestPublicNoArgs); +} +impl TestPublicNoArgs { + #[inline] + pub unsafe fn new() -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + TestPublicNoArgs_TestPublicNoArgs(__bindgen_tmp.as_mut_ptr()); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/contains-vs-inherits-zero-sized.rs b/bindgen-tests/tests/expectations/tests/contains-vs-inherits-zero-sized.rs new file mode 100644 index 0000000000..3362280843 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/contains-vs-inherits-zero-sized.rs @@ -0,0 +1,42 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// This should get an `_address` byte. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Empty { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Empty"][::std::mem::size_of::() - 1usize]; + ["Alignment of Empty"][::std::mem::align_of::() - 1usize]; +}; +/** This should not get an `_address` byte, so `sizeof(Inherits)` should be + `1`.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Inherits { + pub b: bool, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Inherits"][::std::mem::size_of::() - 1usize]; + ["Alignment of Inherits"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Inherits::b"][::std::mem::offset_of!(Inherits, b) - 0usize]; +}; +/** This should not get an `_address` byte, but contains `Empty` which *does* get + one, so `sizeof(Contains)` should be `1 + 1`.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Contains { + pub empty: Empty, + pub b: bool, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Contains"][::std::mem::size_of::() - 2usize]; + ["Alignment of Contains"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: Contains::empty", + ][::std::mem::offset_of!(Contains, empty) - 0usize]; + ["Offset of field: Contains::b"][::std::mem::offset_of!(Contains, b) - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/convert-cpp-comment-to-rust.rs b/bindgen-tests/tests/expectations/tests/convert-cpp-comment-to-rust.rs new file mode 100644 index 0000000000..96f9e6fd2a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/convert-cpp-comment-to-rust.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type mbedtls_mpi_uint = ::std::os::raw::c_uint; +/// \brief MPI structure +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct mbedtls_mpi { + ///< integer sign + pub s: ::std::os::raw::c_int, + ///< total # of limbs + pub n: ::std::os::raw::c_ulong, + ///< pointer to limbs + pub p: *mut mbedtls_mpi_uint, +} +impl Default for mbedtls_mpi { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/convert-floats.rs b/bindgen-tests/tests/expectations/tests/convert-floats.rs new file mode 100644 index 0000000000..9ca939f7c5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/convert-floats.rs @@ -0,0 +1,41 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub bar: ::std::os::raw::c_float, + pub baz: ::std::os::raw::c_float, + pub bazz: ::std::os::raw::c_double, + pub bazzz: *mut u128, + pub complexFloat: __BindgenComplex<::std::os::raw::c_float>, + pub complexDouble: __BindgenComplex<::std::os::raw::c_double>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 48usize]; + ["Alignment of foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; + ["Offset of field: foo::baz"][::std::mem::offset_of!(foo, baz) - 4usize]; + ["Offset of field: foo::bazz"][::std::mem::offset_of!(foo, bazz) - 8usize]; + ["Offset of field: foo::bazzz"][::std::mem::offset_of!(foo, bazzz) - 16usize]; + [ + "Offset of field: foo::complexFloat", + ][::std::mem::offset_of!(foo, complexFloat) - 24usize]; + [ + "Offset of field: foo::complexDouble", + ][::std::mem::offset_of!(foo, complexDouble) - 32usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/core_ffi_c.rs b/bindgen-tests/tests/expectations/tests/core_ffi_c.rs new file mode 100644 index 0000000000..42c9272034 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/core_ffi_c.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type c_char = ::core::ffi::c_char; +pub type c_double = ::core::ffi::c_double; +pub type c_float = ::core::ffi::c_float; +pub type c_int = ::core::ffi::c_int; +pub type c_long = ::core::ffi::c_long; +pub type c_longlong = ::core::ffi::c_longlong; +pub type c_schar = ::core::ffi::c_schar; +pub type c_short = ::core::ffi::c_short; +pub type c_uchar = ::core::ffi::c_uchar; +pub type c_uint = ::core::ffi::c_uint; +pub type c_ulong = ::core::ffi::c_ulong; +pub type c_ulonglong = ::core::ffi::c_ulonglong; +pub type c_ushort = ::core::ffi::c_ushort; diff --git a/bindgen-tests/tests/expectations/tests/cpp-empty-layout.rs b/bindgen-tests/tests/expectations/tests/cpp-empty-layout.rs new file mode 100644 index 0000000000..551dff82cf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/cpp-empty-layout.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/crtp.rs b/bindgen-tests/tests/expectations/tests/crtp.rs new file mode 100644 index 0000000000..68397041b7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/crtp.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Base { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Derived { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Derived"][::std::mem::size_of::() - 1usize]; + ["Alignment of Derived"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct BaseWithDestructor { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct DerivedFromBaseWithDestructor { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of DerivedFromBaseWithDestructor", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of DerivedFromBaseWithDestructor", + ][::std::mem::align_of::() - 1usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Base_open0_Derived_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: Base_open0_Derived_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: BaseWithDestructor_open0_DerivedFromBaseWithDestructor_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: BaseWithDestructor_open0_DerivedFromBaseWithDestructor_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/ctypes-prefix-path.rs b/bindgen-tests/tests/expectations/tests/ctypes-prefix-path.rs new file mode 100644 index 0000000000..5f947f9cea --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/ctypes-prefix-path.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![no_std] +mod libc { + pub mod foo { + pub type c_int = i32; + pub enum c_void {} + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub a: libc::foo::c_int, + pub b: libc::foo::c_int, + pub bar: *mut libc::foo::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::core::mem::size_of::() - 16usize]; + ["Alignment of foo"][::core::mem::align_of::() - 8usize]; + ["Offset of field: foo::a"][::core::mem::offset_of!(foo, a) - 0usize]; + ["Offset of field: foo::b"][::core::mem::offset_of!(foo, b) - 4usize]; + ["Offset of field: foo::bar"][::core::mem::offset_of!(foo, bar) - 8usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/dash_language.rs b/bindgen-tests/tests/expectations/tests/dash_language.rs similarity index 78% rename from tests/expectations/tests/dash_language.rs rename to bindgen-tests/tests/expectations/tests/dash_language.rs index f6d15d1c24..f405a35604 100644 --- a/tests/expectations/tests/dash_language.rs +++ b/bindgen-tests/tests/expectations/tests/dash_language.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Foo { diff --git a/bindgen-tests/tests/expectations/tests/decl_extern_int_twice.rs b/bindgen-tests/tests/expectations/tests/decl_extern_int_twice.rs new file mode 100644 index 0000000000..122d41a12d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/decl_extern_int_twice.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut foo: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/decl_ptr_to_array.rs b/bindgen-tests/tests/expectations/tests/decl_ptr_to_array.rs new file mode 100644 index 0000000000..a559d33b4a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/decl_ptr_to_array.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut foo: *mut [::std::os::raw::c_int; 1usize]; +} diff --git a/bindgen-tests/tests/expectations/tests/default-enum-style-constified-module.rs b/bindgen-tests/tests/expectations/tests/default-enum-style-constified-module.rs new file mode 100644 index 0000000000..2a75aa8d86 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default-enum-style-constified-module.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const bar: Type = 0; + pub const baz: Type = 1; + pub const blap: Type = 2; +} +unsafe extern "C" { + pub fn func(x: Foo::Type); +} diff --git a/bindgen-tests/tests/expectations/tests/default-macro-constant-type-signed.rs b/bindgen-tests/tests/expectations/tests/default-macro-constant-type-signed.rs new file mode 100644 index 0000000000..7fca57b6b9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default-macro-constant-type-signed.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const N0: i32 = 0; +pub const N1: i32 = 1; +pub const N2: i32 = 2; +pub const N_1: i32 = -1; +pub const N_2: i32 = -2; +pub const MAX_U16: i32 = 65535; +pub const MAX_I16: i32 = 32767; +pub const MAX_I16_Plus1: i32 = 32768; +pub const MAX_U16_Plus1: i32 = 65536; +pub const MAX_I16_Minus1: i32 = 32766; +pub const MAX_U16_Minus1: i32 = 65534; +pub const MIN_U16: i32 = 0; +pub const MIN_I16: i32 = -32768; +pub const MIN_U16_Plus1: i32 = 1; +pub const MIN_I16_Plus1: i32 = -32767; +pub const MIN_U16_Minus1: i32 = -1; +pub const MIN_I16_Minus1: i32 = -32769; +pub const MAX_U32: i64 = 4294967295; +pub const MAX_I32: i32 = 2147483647; +pub const MAX_I32_Plus1: i64 = 2147483648; +pub const MAX_U32_Plus1: i64 = 4294967296; +pub const MAX_I32_Minus1: i32 = 2147483646; +pub const MAX_U32_Minus1: i64 = 4294967294; +pub const MIN_U32: i32 = 0; +pub const MIN_I32: i32 = -2147483648; +pub const MIN_U32_Plus1: i32 = 1; +pub const MIN_I32_Plus1: i32 = -2147483647; +pub const MIN_U32_Minus1: i32 = -1; +pub const MIN_I32_Minus1: i64 = -2147483649; +pub const LONG12: i64 = 123456789012; +pub const LONG_12: i64 = -123456789012; +unsafe extern "C" { + pub fn foo( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_uint, + arg4: ::std::os::raw::c_char, + arg5: ::std::os::raw::c_uchar, + arg6: ::std::os::raw::c_schar, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar( + arg1: ::std::os::raw::c_long, + arg2: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_long; +} diff --git a/bindgen-tests/tests/expectations/tests/default-macro-constant-type-unsigned.rs b/bindgen-tests/tests/expectations/tests/default-macro-constant-type-unsigned.rs new file mode 100644 index 0000000000..d34d050a1a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default-macro-constant-type-unsigned.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const N0: u32 = 0; +pub const N1: u32 = 1; +pub const N2: u32 = 2; +pub const N_1: i32 = -1; +pub const N_2: i32 = -2; +pub const MAX_U16: u32 = 65535; +pub const MAX_I16: u32 = 32767; +pub const MAX_I16_Plus1: u32 = 32768; +pub const MAX_U16_Plus1: u32 = 65536; +pub const MAX_I16_Minus1: u32 = 32766; +pub const MAX_U16_Minus1: u32 = 65534; +pub const MIN_U16: u32 = 0; +pub const MIN_I16: i32 = -32768; +pub const MIN_U16_Plus1: u32 = 1; +pub const MIN_I16_Plus1: i32 = -32767; +pub const MIN_U16_Minus1: i32 = -1; +pub const MIN_I16_Minus1: i32 = -32769; +pub const MAX_U32: u32 = 4294967295; +pub const MAX_I32: u32 = 2147483647; +pub const MAX_I32_Plus1: u32 = 2147483648; +pub const MAX_U32_Plus1: u64 = 4294967296; +pub const MAX_I32_Minus1: u32 = 2147483646; +pub const MAX_U32_Minus1: u32 = 4294967294; +pub const MIN_U32: u32 = 0; +pub const MIN_I32: i32 = -2147483648; +pub const MIN_U32_Plus1: u32 = 1; +pub const MIN_I32_Plus1: i32 = -2147483647; +pub const MIN_U32_Minus1: i32 = -1; +pub const MIN_I32_Minus1: i64 = -2147483649; +pub const LONG12: u64 = 123456789012; +pub const LONG_12: i64 = -123456789012; +unsafe extern "C" { + pub fn foo( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_uint, + arg4: ::std::os::raw::c_char, + arg5: ::std::os::raw::c_uchar, + arg6: ::std::os::raw::c_schar, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar( + arg1: ::std::os::raw::c_long, + arg2: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_long; +} diff --git a/bindgen-tests/tests/expectations/tests/default-macro-constant-type.rs b/bindgen-tests/tests/expectations/tests/default-macro-constant-type.rs new file mode 100644 index 0000000000..d34d050a1a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default-macro-constant-type.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const N0: u32 = 0; +pub const N1: u32 = 1; +pub const N2: u32 = 2; +pub const N_1: i32 = -1; +pub const N_2: i32 = -2; +pub const MAX_U16: u32 = 65535; +pub const MAX_I16: u32 = 32767; +pub const MAX_I16_Plus1: u32 = 32768; +pub const MAX_U16_Plus1: u32 = 65536; +pub const MAX_I16_Minus1: u32 = 32766; +pub const MAX_U16_Minus1: u32 = 65534; +pub const MIN_U16: u32 = 0; +pub const MIN_I16: i32 = -32768; +pub const MIN_U16_Plus1: u32 = 1; +pub const MIN_I16_Plus1: i32 = -32767; +pub const MIN_U16_Minus1: i32 = -1; +pub const MIN_I16_Minus1: i32 = -32769; +pub const MAX_U32: u32 = 4294967295; +pub const MAX_I32: u32 = 2147483647; +pub const MAX_I32_Plus1: u32 = 2147483648; +pub const MAX_U32_Plus1: u64 = 4294967296; +pub const MAX_I32_Minus1: u32 = 2147483646; +pub const MAX_U32_Minus1: u32 = 4294967294; +pub const MIN_U32: u32 = 0; +pub const MIN_I32: i32 = -2147483648; +pub const MIN_U32_Plus1: u32 = 1; +pub const MIN_I32_Plus1: i32 = -2147483647; +pub const MIN_U32_Minus1: i32 = -1; +pub const MIN_I32_Minus1: i64 = -2147483649; +pub const LONG12: u64 = 123456789012; +pub const LONG_12: i64 = -123456789012; +unsafe extern "C" { + pub fn foo( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_uint, + arg4: ::std::os::raw::c_char, + arg5: ::std::os::raw::c_uchar, + arg6: ::std::os::raw::c_schar, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar( + arg1: ::std::os::raw::c_long, + arg2: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_long; +} diff --git a/bindgen-tests/tests/expectations/tests/default-template-parameter.rs b/bindgen-tests/tests/expectations/tests/default-template-parameter.rs new file mode 100644 index 0000000000..67f8a486de --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default-template-parameter.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, + pub u: U, +} +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Foo_open0_bool__int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: Foo_open0_bool__int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZL3bar"] + pub static mut bar: Foo; +} diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs new file mode 100644 index 0000000000..aeefb2e0f9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs @@ -0,0 +1,301 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Point { + pub(crate) x: ::std::os::raw::c_int, + pub(crate) y: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Color { + pub(crate) _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +impl Color { + #[inline] + pub(crate) fn r(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub(crate) fn set_r(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub(crate) unsafe fn r_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub(crate) unsafe fn set_r_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub(crate) fn g(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub(crate) fn set_g(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub(crate) unsafe fn g_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub(crate) unsafe fn set_g_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub(crate) fn b(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } + } + #[inline] + pub(crate) fn set_b(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub(crate) unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) as u8, + ) + } + } + #[inline] + pub(crate) unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub(crate) fn new_bitfield_1( + r: ::std::os::raw::c_char, + g: ::std::os::raw::c_char, + b: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let r: u8 = unsafe { ::std::mem::transmute(r) }; + r as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let g: u8 = unsafe { ::std::mem::transmute(g) }; + g as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs new file mode 100644 index 0000000000..dceed75e36 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs @@ -0,0 +1,301 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Point { + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Color { + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +impl Color { + #[inline] + fn r(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + fn set_r(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + unsafe fn r_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + unsafe fn set_r_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn g(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + fn set_g(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + unsafe fn g_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + unsafe fn set_g_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn b(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } + } + #[inline] + fn set_b(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) as u8, + ) + } + } + #[inline] + unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + r: ::std::os::raw::c_char, + g: ::std::os::raw::c_char, + b: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let r: u8 = unsafe { ::std::mem::transmute(r) }; + r as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let g: u8 = unsafe { ::std::mem::transmute(g) }; + g as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs new file mode 100644 index 0000000000..f43be84bb0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs @@ -0,0 +1,301 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Point { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Color { + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +impl Color { + #[inline] + pub fn r(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_r(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn r_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_r_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn g(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub fn set_g(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn g_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_g_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + r: ::std::os::raw::c_char, + g: ::std::os::raw::c_char, + b: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let r: u8 = unsafe { ::std::mem::transmute(r) }; + r as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let g: u8 = unsafe { ::std::mem::transmute(g) }; + g as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/deleted-function.rs b/bindgen-tests/tests/expectations/tests/deleted-function.rs new file mode 100644 index 0000000000..fc8588121f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/deleted-function.rs @@ -0,0 +1,61 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::
() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1A17inline_definitionEv"] + pub fn A_inline_definition(this: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1A22out_of_line_definitionEv"] + pub fn A_out_of_line_definition(this: *mut A); +} +impl A { + #[inline] + pub unsafe fn inline_definition(&mut self) { + A_inline_definition(self) + } + #[inline] + pub unsafe fn out_of_line_definition(&mut self) { + A_out_of_line_definition(self) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct B { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 1usize]; + ["Alignment of B"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 1usize]; + ["Alignment of C"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1CC1ERS_"] + pub fn C_C(this: *mut C, arg1: *mut C); +} +impl C { + #[inline] + pub unsafe fn new(arg1: *mut C) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + C_C(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs b/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs new file mode 100644 index 0000000000..7fa8bc41ab --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs @@ -0,0 +1,256 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +/** Because this struct have array larger than 32 items + and --with-derive-partialeq --impl-partialeq --impl-debug is provided, + this struct should manually implement `Debug` and `PartialEq`.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Foo { + pub large: [::std::os::raw::c_int; 33usize], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub __bindgen_padding_0: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 136usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::large"][::std::mem::offset_of!(Foo, large) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo4typeEv"] + pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_char; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo9set_type_Ec"] + pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_char); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo8set_typeEc"] + pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_char); +} +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Foo { + #[inline] + pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u8) } + } + #[inline] + pub fn set_type__bindgen_bitfield(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn type__bindgen_bitfield_raw( + this: *const Self, + ) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 3u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_type__bindgen_bitfield_raw( + this: *mut Self, + val: ::std::os::raw::c_char, + ) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + type__bindgen_bitfield: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let type__bindgen_bitfield: u8 = unsafe { + ::std::mem::transmute(type__bindgen_bitfield) + }; + type__bindgen_bitfield as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub unsafe fn type_(&mut self) -> ::std::os::raw::c_char { + Foo_type(self) + } + #[inline] + pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_char) { + Foo_set_type_(self, c) + } + #[inline] + pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_char) { + Foo_set_type(self, c) + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-clone.rs b/bindgen-tests/tests/expectations/tests/derive-clone.rs new file mode 100644 index 0000000000..ccbdf5bd70 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-clone.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// This struct should derive `Clone`. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ShouldDeriveClone { + pub large: [::std::os::raw::c_int; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ShouldDeriveClone"][::std::mem::size_of::() - 132usize]; + [ + "Alignment of ShouldDeriveClone", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ShouldDeriveClone::large", + ][::std::mem::offset_of!(ShouldDeriveClone, large) - 0usize]; +}; +impl Default for ShouldDeriveClone { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-custom-cli.rs b/bindgen-tests/tests/expectations/tests/derive-custom-cli.rs new file mode 100644 index 0000000000..59a3a76571 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-custom-cli.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Clone, Default)] +pub struct foo_struct { + pub inner: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo_struct"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo_struct"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo_struct::inner", + ][::std::mem::offset_of!(foo_struct, inner) - 0usize]; +}; +#[repr(u32)] +#[derive(Clone, Hash, PartialEq, Eq, Copy)] +pub enum foo_enum { + inner = 0, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub union foo_union { + pub fst: ::std::mem::ManuallyDrop<::std::os::raw::c_int>, + pub snd: ::std::mem::ManuallyDrop, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo_union"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo_union"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo_union::fst"][::std::mem::offset_of!(foo_union, fst) - 0usize]; + ["Offset of field: foo_union::snd"][::std::mem::offset_of!(foo_union, snd) - 0usize]; +}; +#[repr(C)] +pub struct non_matching { + pub inner: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of non_matching"][::std::mem::size_of::() - 4usize]; + ["Alignment of non_matching"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: non_matching::inner", + ][::std::mem::offset_of!(non_matching, inner) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-custom.rs b/bindgen-tests/tests/expectations/tests/derive-custom.rs new file mode 100644 index 0000000000..9a69ebbb73 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-custom.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Default, Debug)] +pub struct my_type { + pub a: ::std::os::raw::c_int, +} +/**
+
*/ +#[repr(C)] +#[derive(Default, Debug, Clone)] +pub struct my_type2 { + pub a: ::std::os::raw::c_uint, +} +///
+#[repr(C)] +#[derive(Default, Debug, Clone)] +pub struct my_type3 { + pub a: ::std::os::raw::c_ulong, +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs new file mode 100644 index 0000000000..87cbb7346c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs @@ -0,0 +1,263 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub large_array: [::std::os::raw::c_int; 50usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 204usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::large_array"][::std::mem::offset_of!(C, large_array) - 4usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl C { + #[inline] + pub fn a(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 7u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 7u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs new file mode 100644 index 0000000000..937ad4ad0c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs @@ -0,0 +1,268 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +extern crate core; +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub large_array: [::core::ffi::c_int; 50usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::core::mem::size_of::() - 204usize]; + ["Alignment of C"][::core::mem::align_of::() - 4usize]; + [ + "Offset of field: C::large_array", + ][::core::mem::offset_of!(C, large_array) - 4usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl C { + #[inline] + pub fn a(&self) -> bool { + unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + unsafe { + let val: u8 = ::core::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> bool { + unsafe { + ::core::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::core::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::core::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::core::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> bool { + unsafe { ::core::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::core::mem::transmute(val); + self._bitfield_1.set(1usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::core::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::core::ptr::addr_of!((*this)._bitfield_1), 1usize, 7u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::core::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::core::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::core::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 7u8, + { + let b: u8 = unsafe { ::core::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs new file mode 100644 index 0000000000..87cbb7346c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs @@ -0,0 +1,263 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub large_array: [::std::os::raw::c_int; 50usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 204usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::large_array"][::std::mem::offset_of!(C, large_array) - 4usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl C { + #[inline] + pub fn a(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 7u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 7u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-function-pointer.rs b/bindgen-tests/tests/expectations/tests/derive-debug-function-pointer.rs new file mode 100644 index 0000000000..eaaa8ef9d4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-function-pointer.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Nice { + pub pointer: Nice_Function, + pub large_array: [::std::os::raw::c_int; 34usize], +} +pub type Nice_Function = ::std::option::Option< + unsafe extern "C" fn(data: ::std::os::raw::c_int), +>; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Nice"][::std::mem::size_of::() - 144usize]; + ["Alignment of Nice"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Nice::pointer"][::std::mem::offset_of!(Nice, pointer) - 0usize]; + [ + "Offset of field: Nice::large_array", + ][::std::mem::offset_of!(Nice, large_array) - 8usize]; +}; +impl Default for Nice { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-generic.rs b/bindgen-tests/tests/expectations/tests/derive-debug-generic.rs new file mode 100644 index 0000000000..86e530463f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-generic.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug)] +pub struct Generic { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: [T; 40usize], +} +impl Default for Generic { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-mangle-name.rs b/bindgen-tests/tests/expectations/tests/derive-debug-mangle-name.rs new file mode 100644 index 0000000000..34b4a87d65 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-mangle-name.rs @@ -0,0 +1,74 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct perf_event_attr { + pub type_: ::std::os::raw::c_uint, + pub a: f32, + pub __bindgen_anon_1: perf_event_attr__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union perf_event_attr__bindgen_ty_1 { + pub b: ::std::os::raw::c_int, + pub c: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of perf_event_attr__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of perf_event_attr__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: perf_event_attr__bindgen_ty_1::b", + ][::std::mem::offset_of!(perf_event_attr__bindgen_ty_1, b) - 0usize]; + [ + "Offset of field: perf_event_attr__bindgen_ty_1::c", + ][::std::mem::offset_of!(perf_event_attr__bindgen_ty_1, c) - 0usize]; +}; +impl Default for perf_event_attr__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for perf_event_attr__bindgen_ty_1 { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "perf_event_attr__bindgen_ty_1 {{ union }}") + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of perf_event_attr"][::std::mem::size_of::() - 12usize]; + ["Alignment of perf_event_attr"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: perf_event_attr::type_", + ][::std::mem::offset_of!(perf_event_attr, type_) - 0usize]; + [ + "Offset of field: perf_event_attr::a", + ][::std::mem::offset_of!(perf_event_attr, a) - 4usize]; +}; +impl Default for perf_event_attr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl ::std::fmt::Debug for perf_event_attr { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!( + f, + "perf_event_attr {{ type: {:?}, a: {:?}, __bindgen_anon_1: {:?} }}", + self.type_, + self.a, + self.__bindgen_anon_1, + ) + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs b/bindgen-tests/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs new file mode 100644 index 0000000000..9d75e74d77 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Instance { + pub val: __BindgenOpaqueArray<[u32; 50usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Instance"][::std::mem::size_of::() - 200usize]; + ["Alignment of Instance"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Instance::val"][::std::mem::offset_of!(Instance, val) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-opaque.rs b/bindgen-tests/tests/expectations/tests/derive-debug-opaque.rs new file mode 100644 index 0000000000..4ec1fb2a35 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-debug-opaque.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Opaque { + pub _bindgen_opaque_blob: __BindgenOpaqueArray<[u32; 41usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Opaque"][::std::mem::size_of::() - 164usize]; + ["Alignment of Opaque"][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct OpaqueUser { + pub opaque: Opaque, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of OpaqueUser"][::std::mem::size_of::() - 164usize]; + ["Alignment of OpaqueUser"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: OpaqueUser::opaque", + ][::std::mem::offset_of!(OpaqueUser, opaque) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-default-and-blocklist.rs b/bindgen-tests/tests/expectations/tests/derive-default-and-blocklist.rs new file mode 100644 index 0000000000..6ce99e5093 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-default-and-blocklist.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct BlocklistMe(u8); +/** Because this type contains a blocklisted type, it should not derive + Default. Instead, we should emit a `mem::zeroed` implementation.*/ +#[repr(C)] +pub struct ShouldNotDeriveDefault { + pub a: BlocklistMe, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldNotDeriveDefault", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ShouldNotDeriveDefault", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ShouldNotDeriveDefault::a", + ][::std::mem::offset_of!(ShouldNotDeriveDefault, a) - 0usize]; +}; +impl Default for ShouldNotDeriveDefault { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-fn-ptr.rs b/bindgen-tests/tests/expectations/tests/derive-fn-ptr.rs new file mode 100644 index 0000000000..f4b09474ae --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-fn-ptr.rs @@ -0,0 +1,59 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type my_fun_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_int, + arg4: ::std::os::raw::c_int, + arg5: ::std::os::raw::c_int, + arg6: ::std::os::raw::c_int, + arg7: ::std::os::raw::c_int, + arg8: ::std::os::raw::c_int, + arg9: ::std::os::raw::c_int, + arg10: ::std::os::raw::c_int, + arg11: ::std::os::raw::c_int, + arg12: ::std::os::raw::c_int, + arg13: ::std::os::raw::c_int, + arg14: ::std::os::raw::c_int, + arg15: ::std::os::raw::c_int, + arg16: ::std::os::raw::c_int, + ), +>; +#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct Foo { + pub callback: my_fun_t, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Foo::callback"][::std::mem::offset_of!(Foo, callback) - 0usize]; +}; +pub type my_fun2_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_int, + arg4: ::std::os::raw::c_int, + arg5: ::std::os::raw::c_int, + arg6: ::std::os::raw::c_int, + arg7: ::std::os::raw::c_int, + arg8: ::std::os::raw::c_int, + arg9: ::std::os::raw::c_int, + arg10: ::std::os::raw::c_int, + arg11: ::std::os::raw::c_int, + arg12: ::std::os::raw::c_int, + ), +>; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Bar { + pub callback: my_fun2_t, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::callback"][::std::mem::offset_of!(Bar, callback) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-and-blocklist.rs b/bindgen-tests/tests/expectations/tests/derive-hash-and-blocklist.rs new file mode 100644 index 0000000000..c52047e8b8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-and-blocklist.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct BlocklistMe(u8); +/// Because this type contains a blocklisted type, it should not derive Hash. +#[repr(C)] +pub struct ShouldNotDeriveHash { + pub a: BlocklistMe, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldNotDeriveHash", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ShouldNotDeriveHash", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ShouldNotDeriveHash::a", + ][::std::mem::offset_of!(ShouldNotDeriveHash, a) - 0usize]; +}; +impl Default for ShouldNotDeriveHash { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-blocklisting.rs b/bindgen-tests/tests/expectations/tests/derive-hash-blocklisting.rs new file mode 100644 index 0000000000..e3223f08d7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-blocklisting.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] +pub struct Blocklisted { + t: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, +} +/** This would derive(Hash, Eq, PartialEq) if it didn't contain a blocklisted type, + causing us to conservatively avoid deriving hash/Eq/PartialEq for it.*/ +#[repr(C)] +pub struct AllowlistedOne { + pub a: Blocklisted<::std::os::raw::c_int>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistedOne"][::std::mem::size_of::() - 4usize]; + ["Alignment of AllowlistedOne"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: AllowlistedOne::a", + ][::std::mem::offset_of!(AllowlistedOne, a) - 0usize]; +}; +impl Default for AllowlistedOne { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// This can't derive(Hash/Eq) even if it didn't contain a blocklisted type. +#[repr(C)] +pub struct AllowlistedTwo { + pub b: Blocklisted, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AllowlistedTwo"][::std::mem::size_of::() - 4usize]; + ["Alignment of AllowlistedTwo"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: AllowlistedTwo::b", + ][::std::mem::offset_of!(AllowlistedTwo, b) - 0usize]; +}; +impl Default for AllowlistedTwo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs new file mode 100644 index 0000000000..2d66015fe7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// A struct containing a struct containing a float that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] +pub struct foo__bindgen_ty_1 { + pub a: f32, + pub b: f32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-float-array.rs b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-float-array.rs new file mode 100644 index 0000000000..254a50b3e3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-float-array.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// A struct containing an array of floats that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] +pub struct foo { + pub bar: [f32; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 12usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs new file mode 100644 index 0000000000..2588a49eed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs @@ -0,0 +1,80 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct test { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of test"][::std::mem::size_of::() - 4usize]; + ["Alignment of test"][::std::mem::align_of::() - 4usize]; + ["Offset of field: test::a"][::std::mem::offset_of!(test, a) - 0usize]; + [ + "Offset of field: test::zero_length_array", + ][::std::mem::offset_of!(test, zero_length_array) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct test2 { + pub a: ::std::os::raw::c_int, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of test2"][::std::mem::size_of::() - 4usize]; + ["Alignment of test2"][::std::mem::align_of::() - 4usize]; + ["Offset of field: test2::a"][::std::mem::offset_of!(test2, a) - 0usize]; + [ + "Offset of field: test2::incomplete_array", + ][::std::mem::offset_of!(test2, incomplete_array) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct test3 { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of test3"][::std::mem::size_of::() - 4usize]; + ["Alignment of test3"][::std::mem::align_of::() - 4usize]; + ["Offset of field: test3::a"][::std::mem::offset_of!(test3, a) - 0usize]; + [ + "Offset of field: test3::zero_length_array", + ][::std::mem::offset_of!(test3, zero_length_array) - 4usize]; + [ + "Offset of field: test3::incomplete_array", + ][::std::mem::offset_of!(test3, incomplete_array) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-pointer.rs b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-pointer.rs new file mode 100644 index 0000000000..5240d969db --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-struct-with-pointer.rs @@ -0,0 +1,92 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// Pointers can derive Hash/PartialOrd/Ord/PartialEq/Eq +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct ConstPtrMutObj { + pub bar: *mut ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ConstPtrMutObj"][::std::mem::size_of::() - 8usize]; + ["Alignment of ConstPtrMutObj"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ConstPtrMutObj::bar", + ][::std::mem::offset_of!(ConstPtrMutObj, bar) - 0usize]; +}; +impl Default for ConstPtrMutObj { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct MutPtrMutObj { + pub bar: *mut ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of MutPtrMutObj"][::std::mem::size_of::() - 8usize]; + ["Alignment of MutPtrMutObj"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: MutPtrMutObj::bar", + ][::std::mem::offset_of!(MutPtrMutObj, bar) - 0usize]; +}; +impl Default for MutPtrMutObj { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct MutPtrConstObj { + pub bar: *const ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of MutPtrConstObj"][::std::mem::size_of::() - 8usize]; + ["Alignment of MutPtrConstObj"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: MutPtrConstObj::bar", + ][::std::mem::offset_of!(MutPtrConstObj, bar) - 0usize]; +}; +impl Default for MutPtrConstObj { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct ConstPtrConstObj { + pub bar: *const ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ConstPtrConstObj"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of ConstPtrConstObj", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ConstPtrConstObj::bar", + ][::std::mem::offset_of!(ConstPtrConstObj, bar) - 0usize]; +}; +impl Default for ConstPtrConstObj { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-template-def-float.rs b/bindgen-tests/tests/expectations/tests/derive-hash-template-def-float.rs new file mode 100644 index 0000000000..af09533cca --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-template-def-float.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// Template definition containing a float, which cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd. +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +pub struct foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub data: T, + pub b: f32, +} +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-hash-template-inst-float.rs b/bindgen-tests/tests/expectations/tests/derive-hash-template-inst-float.rs new file mode 100644 index 0000000000..10ed002e6e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-hash-template-inst-float.rs @@ -0,0 +1,77 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// Template definition that doesn't contain float can derive Hash/PartialOrd/Ord/PartialEq/Eq +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub data: T, +} +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// Can derive Hash/PartialOrd/Ord/PartialEq/Eq when instantiated with int +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct IntStr { + pub a: foo<::std::os::raw::c_int>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of IntStr"][::std::mem::size_of::() - 4usize]; + ["Alignment of IntStr"][::std::mem::align_of::() - 4usize]; + ["Offset of field: IntStr::a"][::std::mem::offset_of!(IntStr, a) - 0usize]; +}; +impl Default for IntStr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// Cannot derive Hash/Eq/Ord when instantiated with float but can derive PartialEq/PartialOrd +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] +pub struct FloatStr { + pub a: foo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of FloatStr"][::std::mem::size_of::() - 4usize]; + ["Alignment of FloatStr"][::std::mem::align_of::() - 4usize]; + ["Offset of field: FloatStr::a"][::std::mem::offset_of!(FloatStr, a) - 0usize]; +}; +impl Default for FloatStr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: foo_open0_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: foo_open0_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: foo_open0_float_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: foo_open0_float_close0", + ][::std::mem::align_of::>() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-and-blocklist.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-and-blocklist.rs new file mode 100644 index 0000000000..d24981061c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-and-blocklist.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct BlocklistMe(u8); +/** Because this type contains a blocklisted type, it should not derive + PartialEq.*/ +#[repr(C)] +pub struct ShouldNotDerivePartialEq { + pub a: BlocklistMe, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldNotDerivePartialEq", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ShouldNotDerivePartialEq", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ShouldNotDerivePartialEq::a", + ][::std::mem::offset_of!(ShouldNotDerivePartialEq, a) - 0usize]; +}; +impl Default for ShouldNotDerivePartialEq { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-anonfield.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-anonfield.rs new file mode 100644 index 0000000000..c4eb08df60 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-anonfield.rs @@ -0,0 +1,45 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(64))] +#[derive(Copy, Clone)] +pub struct rte_mbuf { + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, +} +#[repr(C)] +#[repr(align(1))] +#[derive(Copy, Clone)] +pub struct rte_mbuf__bindgen_ty_1 { + pub bindgen_union_field: [u8; 0usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_1", + ][::std::mem::size_of::() - 0usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_1", + ][::std::mem::align_of::() - 1usize]; +}; +impl Default for rte_mbuf__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_mbuf"][::std::mem::size_of::() - 0usize]; + ["Alignment of rte_mbuf"][::std::mem::align_of::() - 64usize]; +}; +impl Default for rte_mbuf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-base.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-base.rs new file mode 100644 index 0000000000..3ca262fe36 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-base.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Base { + pub large: [::std::os::raw::c_int; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Base"][::std::mem::size_of::() - 132usize]; + ["Alignment of Base"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Base::large"][::std::mem::offset_of!(Base, large) - 0usize]; +}; +impl Default for Base { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct ShouldDerivePartialEq { + pub _base: Base, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldDerivePartialEq", + ][::std::mem::size_of::() - 132usize]; + [ + "Alignment of ShouldDerivePartialEq", + ][::std::mem::align_of::() - 4usize]; +}; +impl Default for ShouldDerivePartialEq { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs new file mode 100644 index 0000000000..b8da88e2a7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs @@ -0,0 +1,263 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct C { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub large_array: [::std::os::raw::c_int; 50usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 204usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::large_array"][::std::mem::offset_of!(C, large_array) - 4usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl C { + #[inline] + pub fn a(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 7u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 7u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-core.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-core.rs new file mode 100644 index 0000000000..9a36b8f8c7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-core.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +extern crate core; +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct C { + pub large_array: [::core::ffi::c_int; 420usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::core::mem::size_of::() - 1680usize]; + ["Alignment of C"][::core::mem::align_of::() - 4usize]; + [ + "Offset of field: C::large_array", + ][::core::mem::offset_of!(C, large_array) - 0usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-pointer.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-pointer.rs new file mode 100644 index 0000000000..3e48e5d8ce --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-pointer.rs @@ -0,0 +1,79 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Bar { + pub b: *mut a, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::b"][::std::mem::offset_of!(Bar, b) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct c { + pub __bindgen_anon_1: c__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union c__bindgen_ty_1 { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of c__bindgen_ty_1"][::std::mem::size_of::() - 1usize]; + ["Alignment of c__bindgen_ty_1"][::std::mem::align_of::() - 1usize]; +}; +impl Default for c__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of c"][::std::mem::size_of::() - 1usize]; + ["Alignment of c"][::std::mem::align_of::() - 1usize]; +}; +impl Default for c { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct a { + pub d: c, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of a"][::std::mem::size_of::
() - 1usize]; + ["Alignment of a"][::std::mem::align_of::() - 1usize]; + ["Offset of field: a::d"][::std::mem::offset_of!(a, d) - 0usize]; +}; +impl Default for a { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-union.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-union.rs new file mode 100644 index 0000000000..0365c765eb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-union.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// Deriving PartialEq for rust unions is not supported. +#[repr(C)] +#[derive(Copy, Clone)] +pub union ShouldNotDerivePartialEq { + pub a: ::std::os::raw::c_char, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldNotDerivePartialEq", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of ShouldNotDerivePartialEq", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ShouldNotDerivePartialEq::a", + ][::std::mem::offset_of!(ShouldNotDerivePartialEq, a) - 0usize]; + [ + "Offset of field: ShouldNotDerivePartialEq::b", + ][::std::mem::offset_of!(ShouldNotDerivePartialEq, b) - 0usize]; +}; +impl Default for ShouldNotDerivePartialEq { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/disable-namespacing.rs b/bindgen-tests/tests/expectations/tests/disable-namespacing.rs new file mode 100644 index 0000000000..4d9b6a082d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/disable-namespacing.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type Baz = ::std::os::raw::c_int; diff --git a/bindgen-tests/tests/expectations/tests/disable-nested-struct-naming.rs b/bindgen-tests/tests/expectations/tests/disable-nested-struct-naming.rs new file mode 100644 index 0000000000..757e0481aa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/disable-nested-struct-naming.rs @@ -0,0 +1,122 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub b1: bar1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar1 { + pub x1: ::std::os::raw::c_int, + pub b2: bar1__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar1__bindgen_ty_1 { + pub x2: ::std::os::raw::c_int, + pub b3: bar1__bindgen_ty_1__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar1__bindgen_ty_1__bindgen_ty_1 { + pub x3: ::std::os::raw::c_int, + pub b4: bar4, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar4 { + pub x4: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar4"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar4"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar4::x4"][::std::mem::offset_of!(bar4, x4) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of bar1__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of bar1__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: bar1__bindgen_ty_1__bindgen_ty_1::x3", + ][::std::mem::offset_of!(bar1__bindgen_ty_1__bindgen_ty_1, x3) - 0usize]; + [ + "Offset of field: bar1__bindgen_ty_1__bindgen_ty_1::b4", + ][::std::mem::offset_of!(bar1__bindgen_ty_1__bindgen_ty_1, b4) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of bar1__bindgen_ty_1", + ][::std::mem::size_of::() - 12usize]; + [ + "Alignment of bar1__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: bar1__bindgen_ty_1::x2", + ][::std::mem::offset_of!(bar1__bindgen_ty_1, x2) - 0usize]; + [ + "Offset of field: bar1__bindgen_ty_1::b3", + ][::std::mem::offset_of!(bar1__bindgen_ty_1, b3) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar1"][::std::mem::size_of::() - 16usize]; + ["Alignment of bar1"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar1::x1"][::std::mem::offset_of!(bar1, x1) - 0usize]; + ["Offset of field: bar1::b2"][::std::mem::offset_of!(bar1, b2) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 16usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::b1"][::std::mem::offset_of!(foo, b1) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct _bindgen_ty_1 { + pub anon2: _bindgen_ty_1__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct _bindgen_ty_1__bindgen_ty_1 { + pub b: baz, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct baz { + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of baz"][::std::mem::align_of::() - 4usize]; + ["Offset of field: baz::x"][::std::mem::offset_of!(baz, x) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of _bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::<_bindgen_ty_1__bindgen_ty_1>() - 4usize]; + [ + "Alignment of _bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::<_bindgen_ty_1__bindgen_ty_1>() - 4usize]; + [ + "Offset of field: _bindgen_ty_1__bindgen_ty_1::b", + ][::std::mem::offset_of!(_bindgen_ty_1__bindgen_ty_1, b) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 4usize]; + ["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 4usize]; + [ + "Offset of field: _bindgen_ty_1::anon2", + ][::std::mem::offset_of!(_bindgen_ty_1, anon2) - 0usize]; +}; +unsafe extern "C" { + pub static mut anon1: _bindgen_ty_1; +} diff --git a/bindgen-tests/tests/expectations/tests/disable-untagged-union.rs b/bindgen-tests/tests/expectations/tests/disable-untagged-union.rs new file mode 100644 index 0000000000..60636280e4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/disable-untagged-union.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub bar: __BindgenUnionField<::std::os::raw::c_int>, + pub baz: __BindgenUnionField<::std::os::raw::c_uint>, + pub bindgen_union_field: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; + ["Offset of field: Foo::baz"][::std::mem::offset_of!(Foo, baz) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs b/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs new file mode 100644 index 0000000000..37139d3136 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs @@ -0,0 +1,186 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithBitfield { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub a: ::std::os::raw::c_uint, +} +impl WithBitfield { + #[inline] + pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithBitfieldAndAttrPacked { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub a: ::std::os::raw::c_uint, +} +impl WithBitfieldAndAttrPacked { + #[inline] + pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithBitfieldAndPacked { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub a: ::std::os::raw::c_uint, +} +impl WithBitfieldAndPacked { + #[inline] + pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/do-not-derive-copy.rs b/bindgen-tests/tests/expectations/tests/do-not-derive-copy.rs new file mode 100644 index 0000000000..29ca6d6acf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/do-not-derive-copy.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct WouldBeCopyButWeAreNotDerivingCopy { + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of WouldBeCopyButWeAreNotDerivingCopy", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WouldBeCopyButWeAreNotDerivingCopy", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WouldBeCopyButWeAreNotDerivingCopy::x", + ][::std::mem::offset_of!(WouldBeCopyButWeAreNotDerivingCopy, x) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/doggo-or-null.rs b/bindgen-tests/tests/expectations/tests/doggo-or-null.rs new file mode 100644 index 0000000000..972da871d3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/doggo-or-null.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq)] +pub struct Doggo { + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Doggo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Doggo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Doggo::x"][::std::mem::offset_of!(Doggo, x) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq)] +pub struct Null { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Null"][::std::mem::size_of::() - 1usize]; + ["Alignment of Null"][::std::mem::align_of::() - 1usize]; +}; +/** This type is an opaque union. Unions can't derive anything interesting like + Debug or Default, even if their layout can, because it would require knowing + which variant is in use. Opaque unions still end up as a `union` in the Rust + bindings, but they just have one variant. Even so, can't derive. We should + probably emit an opaque struct for opaque unions... but until then, we have + this test to make sure that opaque unions don't derive and still compile.*/ +#[repr(C)] +#[repr(align(4))] +#[derive(Copy, Clone)] +pub union DoggoOrNull { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of DoggoOrNull"][::std::mem::size_of::() - 4usize]; + ["Alignment of DoggoOrNull"][::std::mem::align_of::() - 4usize]; +}; +impl Default for DoggoOrNull { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/dupe-enum-variant-in-namespace.rs b/bindgen-tests/tests/expectations/tests/dupe-enum-variant-in-namespace.rs new file mode 100644 index 0000000000..d521bcc17b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dupe-enum-variant-in-namespace.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + impl root::foo::Bar { + pub const Foo1: root::foo::Bar = Bar::Foo; + } + impl root::foo::Bar { + pub const Foo3: root::foo::Bar = Bar::Foo2; + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum Bar { + Foo = 0, + Foo2 = 1, + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/duplicated-definition-count.rs b/bindgen-tests/tests/expectations/tests/duplicated-definition-count.rs new file mode 100644 index 0000000000..86e1edbbf9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/duplicated-definition-count.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct BitStream { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of BitStream"][::std::mem::size_of::() - 1usize]; + ["Alignment of BitStream"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN9BitStream5WriteEPKcj"] + pub fn BitStream_Write( + this: *mut BitStream, + inputByteArray: *const ::std::os::raw::c_char, + numberOfBytes: ::std::os::raw::c_uint, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN9BitStream5WriteEPS_j"] + pub fn BitStream_Write1( + this: *mut BitStream, + bitStream: *mut BitStream, + numberOfBits: ::std::os::raw::c_uint, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN9BitStream6Write1Ev"] + pub fn BitStream_Write11(this: *mut BitStream); +} +impl BitStream { + #[inline] + pub unsafe fn Write( + &mut self, + inputByteArray: *const ::std::os::raw::c_char, + numberOfBytes: ::std::os::raw::c_uint, + ) { + BitStream_Write(self, inputByteArray, numberOfBytes) + } + #[inline] + pub unsafe fn Write1( + &mut self, + bitStream: *mut BitStream, + numberOfBits: ::std::os::raw::c_uint, + ) { + BitStream_Write1(self, bitStream, numberOfBits) + } + #[inline] + pub unsafe fn Write11(&mut self) { + BitStream_Write11(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/duplicated-namespaces-definitions.rs b/bindgen-tests/tests/expectations/tests/duplicated-namespaces-definitions.rs new file mode 100644 index 0000000000..775a21ac30 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/duplicated-namespaces-definitions.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar { + pub foo: ::std::os::raw::c_int, + pub baz: bool, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::foo"][::std::mem::offset_of!(Bar, foo) - 0usize]; + ["Offset of field: Bar::baz"][::std::mem::offset_of!(Bar, baz) - 4usize]; + }; + } + pub mod bar { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct Foo { + pub ptr: *mut root::foo::Bar, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Foo::ptr"][::std::mem::offset_of!(Foo, ptr) - 0usize]; + }; + impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + } +} diff --git a/tests/expectations/tests/duplicated-namespaces.rs b/bindgen-tests/tests/expectations/tests/duplicated-namespaces.rs similarity index 81% rename from tests/expectations/tests/duplicated-namespaces.rs rename to bindgen-tests/tests/expectations/tests/duplicated-namespaces.rs index a5f2caacca..c652d151b8 100644 --- a/tests/expectations/tests/duplicated-namespaces.rs +++ b/bindgen-tests/tests/expectations/tests/duplicated-namespaces.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] pub mod root { #[allow(unused_imports)] diff --git a/tests/expectations/tests/duplicated_constants_in_ns.rs b/bindgen-tests/tests/expectations/tests/duplicated_constants_in_ns.rs similarity index 91% rename from tests/expectations/tests/duplicated_constants_in_ns.rs rename to bindgen-tests/tests/expectations/tests/duplicated_constants_in_ns.rs index c3f1adde49..2f676374ae 100644 --- a/tests/expectations/tests/duplicated_constants_in_ns.rs +++ b/bindgen-tests/tests/expectations/tests/duplicated_constants_in_ns.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] pub mod root { #[allow(unused_imports)] diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_attributes.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_attributes.rs new file mode 100644 index 0000000000..a1fb1b0cc1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_attributes.rs @@ -0,0 +1,43 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + pub baz: unsafe extern "C" fn() -> ::std::os::raw::c_int, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"foo\0").map(|sym| *sym)?; + let baz = __library.get(b"baz\0").map(|sym| *sym)?; + Ok(TestLib { __library, foo, baz }) + } + #[must_use] + /** @brief A function + + @param x + @param y + @return int*/ + pub unsafe fn foo( + &self, + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int { + (self.foo)(x, y) + } + pub unsafe fn baz(&self) -> ::std::os::raw::c_int { + (self.baz)() + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_required.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_required.rs new file mode 100644 index 0000000000..5c929ffc3d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_required.rs @@ -0,0 +1,49 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + pub bar: unsafe extern "C" fn( + x: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, + pub baz: unsafe extern "C" fn() -> ::std::os::raw::c_int, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"foo\0").map(|sym| *sym)?; + let bar = __library.get(b"bar\0").map(|sym| *sym)?; + let baz = __library.get(b"baz\0").map(|sym| *sym)?; + Ok(TestLib { + __library, + foo, + bar, + baz, + }) + } + pub unsafe fn foo( + &self, + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int { + (self.foo)(x, y) + } + pub unsafe fn bar(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.bar)(x) + } + pub unsafe fn baz(&self) -> ::std::os::raw::c_int { + (self.baz)() + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_simple.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_simple.rs new file mode 100644 index 0000000000..9a4cfaf570 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_simple.rs @@ -0,0 +1,56 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub bar: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub baz: Result< + unsafe extern "C" fn() -> ::std::os::raw::c_int, + ::libloading::Error, + >, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"foo\0").map(|sym| *sym); + let bar = __library.get(b"bar\0").map(|sym| *sym); + let baz = __library.get(b"baz\0").map(|sym| *sym); + Ok(TestLib { + __library, + foo, + bar, + baz, + }) + } + pub unsafe fn foo( + &self, + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int { + (self.foo.as_ref().expect("Expected function, got error."))(x, y) + } + pub unsafe fn bar(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.bar.as_ref().expect("Expected function, got error."))(x) + } + pub unsafe fn baz(&self) -> ::std::os::raw::c_int { + (self.baz.as_ref().expect("Expected function, got error."))() + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs new file mode 100644 index 0000000000..1f63a7893f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn(x: ::std::os::raw::c_int) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub foo1: Result f32, ::libloading::Error>, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"_Z3fooIiET_S0_\0").map(|sym| *sym); + let foo1 = __library.get(b"_Z3fooIfET_S0_\0").map(|sym| *sym); + Ok(TestLib { __library, foo, foo1 }) + } + pub unsafe fn foo(&self, x: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + (self.foo.as_ref().expect("Expected function, got error."))(x) + } + pub unsafe fn foo1(&self, x: f32) -> f32 { + (self.foo1.as_ref().expect("Expected function, got error."))(x) + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_required.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_required.rs new file mode 100644 index 0000000000..a96efbe546 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_required.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: *mut ::std::os::raw::c_int, + pub baz: *mut *mut ::std::os::raw::c_int, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get::<*mut ::std::os::raw::c_int>(b"foo\0").map(|sym| *sym)?; + let baz = __library + .get::<*mut *mut ::std::os::raw::c_int>(b"baz\0") + .map(|sym| *sym)?; + Ok(TestLib { __library, foo, baz }) + } + pub unsafe fn foo(&self) -> *mut ::std::os::raw::c_int { + self.foo + } + pub unsafe fn baz(&self) -> *mut *mut ::std::os::raw::c_int { + self.baz + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_simple.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_simple.rs new file mode 100644 index 0000000000..ced70dbdba --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_simple.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result<*mut ::std::os::raw::c_int, ::libloading::Error>, + pub baz: Result<*mut *mut ::std::os::raw::c_int, ::libloading::Error>, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get::<*mut ::std::os::raw::c_int>(b"foo\0").map(|sym| *sym); + let baz = __library + .get::<*mut *mut ::std::os::raw::c_int>(b"baz\0") + .map(|sym| *sym); + Ok(TestLib { __library, foo, baz }) + } + pub unsafe fn foo(&self) -> *mut ::std::os::raw::c_int { + *self.foo.as_ref().expect("Expected variable, got error.") + } + pub unsafe fn baz(&self) -> *mut *mut ::std::os::raw::c_int { + *self.baz.as_ref().expect("Expected variable, got error.") + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_with_allowlist.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_with_allowlist.rs new file mode 100644 index 0000000000..3f29e73814 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_variable_with_allowlist.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result<*mut ::std::os::raw::c_int, ::libloading::Error>, + pub bar: Result<*mut ::std::os::raw::c_int, ::libloading::Error>, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get::<*mut ::std::os::raw::c_int>(b"foo\0").map(|sym| *sym); + let bar = __library.get::<*mut ::std::os::raw::c_int>(b"bar\0").map(|sym| *sym); + Ok(TestLib { __library, foo, bar }) + } + pub unsafe fn foo(&self) -> *mut ::std::os::raw::c_int { + *self.foo.as_ref().expect("Expected variable, got error.") + } + pub unsafe fn bar(&self) -> *mut ::std::os::raw::c_int { + *self.bar.as_ref().expect("Expected variable, got error.") + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs new file mode 100644 index 0000000000..34ebe8d9a5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs @@ -0,0 +1,46 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub baz: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub bazz: Result< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int, ...) -> ::std::os::raw::c_int, + ::libloading::Error, + >, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let baz = __library.get(b"_Z3bazPv\0").map(|sym| *sym); + let bazz = __library.get(b"_Z4bazziz\0").map(|sym| *sym); + Ok(TestLib { + __library, + foo, + baz, + bazz, + }) + } + pub unsafe fn foo(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.foo.as_ref().expect("Expected function, got error."))(x) + } + pub unsafe fn baz(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.baz.as_ref().expect("Expected function, got error."))(x) + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs new file mode 100644 index 0000000000..8c86674f7a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs @@ -0,0 +1,75 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct X { + pub _x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of X"][::std::mem::size_of::() - 4usize]; + ["Alignment of X"][::std::mem::align_of::() - 4usize]; + ["Offset of field: X::_x"][::std::mem::offset_of!(X, _x) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1X13some_functionEv"] + pub fn X_some_function(this: *mut X); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1X19some_other_functionEv"] + pub fn X_some_other_function(this: *mut X); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1XC1Ei"] + pub fn X_X(this: *mut X, x: ::std::os::raw::c_int); +} +impl X { + #[inline] + pub unsafe fn some_function(&mut self) { + X_some_function(self) + } + #[inline] + pub unsafe fn some_other_function(&mut self) { + X_some_other_function(self) + } + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + X_X(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } +} +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub bar: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let bar = __library.get(b"_Z3barPv\0").map(|sym| *sym); + Ok(TestLib { __library, foo, bar }) + } + pub unsafe fn foo(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.foo.as_ref().expect("Expected function, got error."))(x) + } + pub unsafe fn bar(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.bar.as_ref().expect("Expected function, got error."))(x) + } +} diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs new file mode 100644 index 0000000000..65ff2b2f72 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs @@ -0,0 +1,72 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 4usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::_x"][::std::mem::offset_of!(A, _x) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1A13some_functionEv"] + pub fn A_some_function(this: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1A19some_other_functionEv"] + pub fn A_some_other_function(this: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1AC1Ei"] + pub fn A_A(this: *mut A, x: ::std::os::raw::c_int); +} +impl A { + #[inline] + pub unsafe fn some_function(&mut self) { + A_some_function(self) + } + #[inline] + pub unsafe fn some_other_function(&mut self) { + A_some_other_function(self) + } + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + A_A(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } +} +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub bar: Result, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let bar = __library.get(b"_Z3barv\0").map(|sym| *sym); + Ok(TestLib { __library, foo, bar }) + } + pub unsafe fn foo(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + (self.foo.as_ref().expect("Expected function, got error."))(x) + } + pub unsafe fn bar(&self) { + (self.bar.as_ref().expect("Expected function, got error."))() + } +} diff --git a/tests/expectations/tests/elaborated.rs b/bindgen-tests/tests/expectations/tests/elaborated.rs similarity index 78% rename from tests/expectations/tests/elaborated.rs rename to bindgen-tests/tests/expectations/tests/elaborated.rs index f68b55af0d..81c0733089 100644 --- a/tests/expectations/tests/elaborated.rs +++ b/bindgen-tests/tests/expectations/tests/elaborated.rs @@ -1,11 +1,6 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - pub type whatever_whatever_t = ::std::os::raw::c_int; -extern "C" { +unsafe extern "C" { #[link_name = "\u{1}_Z9somethingPKi"] pub fn something(wat: *const whatever_whatever_t); } diff --git a/bindgen-tests/tests/expectations/tests/empty-enum.rs b/bindgen-tests/tests/expectations/tests/empty-enum.rs new file mode 100644 index 0000000000..d19aa41845 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/empty-enum.rs @@ -0,0 +1,34 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type EmptyConstified = ::std::os::raw::c_uint; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum EmptyRustified { + __bindgen_cannot_repr_c_on_empty_enum = 0, +} +pub mod EmptyModule { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; +} +#[repr(i8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum EmptyClassRustified { + __bindgen_cannot_repr_c_on_empty_enum = 0, +} +pub type EmptyClassConstified = ::std::os::raw::c_char; +pub mod EmptyClassModule { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_char; +} +#[repr(i8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum ForwardClassRustified { + __bindgen_cannot_repr_c_on_empty_enum = 0, +} +pub type ForwardClassConstified = ::std::os::raw::c_char; +pub mod ForwardClassModule { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_char; +} diff --git a/bindgen-tests/tests/expectations/tests/empty-union.rs b/bindgen-tests/tests/expectations/tests/empty-union.rs new file mode 100644 index 0000000000..de0f806eb5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/empty-union.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union a__bindgen_ty_1 { + pub _address: u8, +} +impl Default for a__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/empty_template_param_name.rs b/bindgen-tests/tests/expectations/tests/empty_template_param_name.rs similarity index 83% rename from tests/expectations/tests/empty_template_param_name.rs rename to bindgen-tests/tests/expectations/tests/empty_template_param_name.rs index 30289ce48a..db5764ab25 100644 --- a/tests/expectations/tests/empty_template_param_name.rs +++ b/bindgen-tests/tests/expectations/tests/empty_template_param_name.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - pub type __void_t = ::std::os::raw::c_void; #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/bindgen-tests/tests/expectations/tests/enum-default-bitfield.rs b/bindgen-tests/tests/expectations/tests/enum-default-bitfield.rs new file mode 100644 index 0000000000..dda688617c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-default-bitfield.rs @@ -0,0 +1,160 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1, +} +pub const foo_FOO_A: foo__bindgen_ty_1 = foo__bindgen_ty_1(0); +pub const foo_FOO_B: foo__bindgen_ty_1 = foo__bindgen_ty_1(1); +impl ::std::ops::BitOr for foo__bindgen_ty_1 { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + foo__bindgen_ty_1(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for foo__bindgen_ty_1 { + #[inline] + fn bitor_assign(&mut self, rhs: foo__bindgen_ty_1) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for foo__bindgen_ty_1 { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + foo__bindgen_ty_1(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for foo__bindgen_ty_1 { + #[inline] + fn bitand_assign(&mut self, rhs: foo__bindgen_ty_1) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1(pub ::std::os::raw::c_uint); +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Foo { + pub const Bar: Foo = Foo(0); + pub const Qux: Foo = Foo(1); +} +impl ::std::ops::BitOr for Foo { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Foo { + #[inline] + fn bitor_assign(&mut self, rhs: Foo) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Foo { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Foo { + #[inline] + fn bitand_assign(&mut self, rhs: Foo) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_uint); +pub mod Neg { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const MinusOne: Type = -1; + pub const One: Type = 1; +} +impl NoDebug { + pub const NoDebug1: NoDebug = NoDebug(0); + pub const NoDebug2: NoDebug = NoDebug(1); +} +impl ::std::ops::BitOr for NoDebug { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + NoDebug(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for NoDebug { + #[inline] + fn bitor_assign(&mut self, rhs: NoDebug) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for NoDebug { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + NoDebug(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for NoDebug { + #[inline] + fn bitand_assign(&mut self, rhs: NoDebug) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +///

+#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub struct NoDebug(pub ::std::os::raw::c_uint); +impl Debug { + pub const Debug1: Debug = Debug(0); + pub const Debug2: Debug = Debug(1); +} +impl ::std::ops::BitOr for Debug { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Debug(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Debug { + #[inline] + fn bitor_assign(&mut self, rhs: Debug) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Debug { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Debug(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Debug { + #[inline] + fn bitand_assign(&mut self, rhs: Debug) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +///
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Debug(pub ::std::os::raw::c_uint); diff --git a/bindgen-tests/tests/expectations/tests/enum-default-consts.rs b/bindgen-tests/tests/expectations/tests/enum-default-consts.rs new file mode 100644 index 0000000000..1432182310 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-default-consts.rs @@ -0,0 +1,42 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1, +} +pub const foo_FOO_A: foo__bindgen_ty_1 = 0; +pub const foo_FOO_B: foo__bindgen_ty_1 = 1; +pub type foo__bindgen_ty_1 = ::std::os::raw::c_uint; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const Foo_Bar: Foo = 0; +pub const Foo_Qux: Foo = 1; +pub type Foo = ::std::os::raw::c_uint; +pub mod Neg { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const MinusOne: Type = -1; + pub const One: Type = 1; +} +pub const NoDebug_NoDebug1: NoDebug = 0; +pub const NoDebug_NoDebug2: NoDebug = 1; +///
+pub type NoDebug = ::std::os::raw::c_uint; +pub const Debug_Debug1: Debug = 0; +pub const Debug_Debug2: Debug = 1; +///
+pub type Debug = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/enum-default-module.rs b/bindgen-tests/tests/expectations/tests/enum-default-module.rs new file mode 100644 index 0000000000..23fbd22c6e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-default-module.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1::Type, +} +pub mod foo__bindgen_ty_1 { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const FOO_A: Type = 0; + pub const FOO_B: Type = 1; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub mod Foo { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const Bar: Type = 0; + pub const Qux: Type = 1; +} +pub mod Neg { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const MinusOne: Type = -1; + pub const One: Type = 1; +} +pub mod NoDebug { + #[allow(unused_imports)] + use super::*; + ///
+ pub type Type = ::std::os::raw::c_uint; + pub const NoDebug1: Type = 0; + pub const NoDebug2: Type = 1; +} +pub mod Debug { + #[allow(unused_imports)] + use super::*; + ///
+ pub type Type = ::std::os::raw::c_uint; + pub const Debug1: Type = 0; + pub const Debug2: Type = 1; +} diff --git a/bindgen-tests/tests/expectations/tests/enum-default-rust.d b/bindgen-tests/tests/expectations/tests/enum-default-rust.d new file mode 100644 index 0000000000..a6540005c9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-default-rust.d @@ -0,0 +1 @@ +tests/expectations/tests/enum-default-rust.rs: tests/headers/enum-default-rust.h tests/headers/enum.h diff --git a/bindgen-tests/tests/expectations/tests/enum-default-rust.rs b/bindgen-tests/tests/expectations/tests/enum-default-rust.rs new file mode 100644 index 0000000000..59901a78ac --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-default-rust.rs @@ -0,0 +1,56 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1, +} +pub const foo_FOO_A: foo__bindgen_ty_1 = foo__bindgen_ty_1::FOO_A; +pub const foo_FOO_B: foo__bindgen_ty_1 = foo__bindgen_ty_1::FOO_B; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum foo__bindgen_ty_1 { + FOO_A = 0, + FOO_B = 1, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 0, + Qux = 1, +} +pub mod Neg { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const MinusOne: Type = -1; + pub const One: Type = 1; +} +#[repr(u32)] +///
+#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub enum NoDebug { + NoDebug1 = 0, + NoDebug2 = 1, +} +#[repr(u32)] +///
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Debug { + Debug1 = 0, + Debug2 = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/enum-doc-bitfield.rs b/bindgen-tests/tests/expectations/tests/enum-doc-bitfield.rs new file mode 100644 index 0000000000..33eec3e44f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-doc-bitfield.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl B { + /// Document field with three slashes + pub const VAR_A: B = B(0); + /// Document field with preceding star + pub const VAR_B: B = B(1); + /// Document field with preceding exclamation + pub const VAR_C: B = B(2); + ///< Document field with following star + pub const VAR_D: B = B(3); + ///< Document field with following exclamation + pub const VAR_E: B = B(4); + /** Document field with preceding star, with a loong long multiline + comment. + + Very interesting documentation, definitely.*/ + pub const VAR_F: B = B(5); +} +impl ::std::ops::BitOr for B { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + B(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for B { + #[inline] + fn bitor_assign(&mut self, rhs: B) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for B { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + B(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for B { + #[inline] + fn bitand_assign(&mut self, rhs: B) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +/// Document enum +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct B(pub ::std::os::raw::c_uint); diff --git a/bindgen-tests/tests/expectations/tests/enum-doc-mod.rs b/bindgen-tests/tests/expectations/tests/enum-doc-mod.rs new file mode 100644 index 0000000000..580d8165ac --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-doc-mod.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod B { + #[allow(unused_imports)] + use super::*; + /// Document enum + pub type Type = ::std::os::raw::c_uint; + /// Document field with three slashes + pub const VAR_A: Type = 0; + /// Document field with preceding star + pub const VAR_B: Type = 1; + /// Document field with preceding exclamation + pub const VAR_C: Type = 2; + ///< Document field with following star + pub const VAR_D: Type = 3; + ///< Document field with following exclamation + pub const VAR_E: Type = 4; + /** Document field with preceding star, with a loong long multiline + comment. + + Very interesting documentation, definitely.*/ + pub const VAR_F: Type = 5; +} diff --git a/bindgen-tests/tests/expectations/tests/enum-doc-rusty-non-exhaustive.rs b/bindgen-tests/tests/expectations/tests/enum-doc-rusty-non-exhaustive.rs new file mode 100644 index 0000000000..1d09466119 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-doc-rusty-non-exhaustive.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u32)] +#[non_exhaustive] +/// Document enum +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum B { + /// Document field with three slashes + VAR_A = 0, + /// Document field with preceding star + VAR_B = 1, + /// Document field with preceding exclamation + VAR_C = 2, + ///< Document field with following star + VAR_D = 3, + ///< Document field with following exclamation + VAR_E = 4, + /** Document field with preceding star, with a loong long multiline + comment. + + Very interesting documentation, definitely.*/ + VAR_F = 5, +} diff --git a/bindgen-tests/tests/expectations/tests/enum-doc-rusty.rs b/bindgen-tests/tests/expectations/tests/enum-doc-rusty.rs new file mode 100644 index 0000000000..3eec0759c5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-doc-rusty.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u32)] +/// Document enum +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum B { + /// Document field with three slashes + VAR_A = 0, + /// Document field with preceding star + VAR_B = 1, + /// Document field with preceding exclamation + VAR_C = 2, + ///< Document field with following star + VAR_D = 3, + ///< Document field with following exclamation + VAR_E = 4, + /** Document field with preceding star, with a loong long multiline + comment. + + Very interesting documentation, definitely.*/ + VAR_F = 5, +} diff --git a/bindgen-tests/tests/expectations/tests/enum-doc.rs b/bindgen-tests/tests/expectations/tests/enum-doc.rs new file mode 100644 index 0000000000..98a7eed8f8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-doc.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/// Document field with three slashes +pub const B_VAR_A: B = 0; +/// Document field with preceding star +pub const B_VAR_B: B = 1; +/// Document field with preceding exclamation +pub const B_VAR_C: B = 2; +///< Document field with following star +pub const B_VAR_D: B = 3; +///< Document field with following exclamation +pub const B_VAR_E: B = 4; +/** Document field with preceding star, with a loong long multiline + comment. + + Very interesting documentation, definitely.*/ +pub const B_VAR_F: B = 5; +/// Document enum +pub type B = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/enum-no-debug-rust.rs b/bindgen-tests/tests/expectations/tests/enum-no-debug-rust.rs new file mode 100644 index 0000000000..643577e1e3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-no-debug-rust.rs @@ -0,0 +1,56 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1, +} +pub const foo_FOO_A: foo__bindgen_ty_1 = foo__bindgen_ty_1::FOO_A; +pub const foo_FOO_B: foo__bindgen_ty_1 = foo__bindgen_ty_1::FOO_B; +#[repr(u32)] +#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub enum foo__bindgen_ty_1 { + FOO_A = 0, + FOO_B = 1, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(u32)] +#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 0, + Qux = 1, +} +pub mod Neg { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_int; + pub const MinusOne: Type = -1; + pub const One: Type = 1; +} +#[repr(u32)] +///
+#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub enum NoDebug { + NoDebug1 = 0, + NoDebug2 = 1, +} +#[repr(u32)] +///
+#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] +pub enum Debug { + Debug1 = 0, + Debug2 = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/enum-translate-type.rs b/bindgen-tests/tests/expectations/tests/enum-translate-type.rs new file mode 100644 index 0000000000..2431e48d5b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-translate-type.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const my_enum1_A: my_enum1 = 0; +pub type my_enum1 = u32; +pub const my_enum2_B: my_enum2 = -1; +pub type my_enum2 = i32; +pub const my_enum3_C: my_enum3 = 0; +pub type my_enum3 = i16; +pub const my_enum4_D: my_enum4 = 255; +pub type my_enum4 = u8; diff --git a/bindgen-tests/tests/expectations/tests/enum-typedef.rs b/bindgen-tests/tests/expectations/tests/enum-typedef.rs new file mode 100644 index 0000000000..772184b39f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-typedef.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const Enum_Variant: Enum = 0; +pub type Enum = i16; +pub type TypedefFirst = i16; +pub const TypedefFirst_Variant2: TypedefFirst = 0; diff --git a/bindgen-tests/tests/expectations/tests/enum-undefault.rs b/bindgen-tests/tests/expectations/tests/enum-undefault.rs new file mode 100644 index 0000000000..01a7aa3cea --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-undefault.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 0, + Qux = 1, +} +pub const Neg_MinusOne: Neg = -1; +pub const Neg_One: Neg = 1; +pub type Neg = ::std::os::raw::c_int; diff --git a/bindgen-tests/tests/expectations/tests/enum-variant-replaces.rs b/bindgen-tests/tests/expectations/tests/enum-variant-replaces.rs new file mode 100644 index 0000000000..a661ca833b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum-variant-replaces.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/**
+ + Should see PASS below.*/ +pub const OGRErr_PASS: OGRErr = 0; +/**
+ + Should see OGRERR_NONE instead of CUSTOM_OGRERR_NONE below.*/ +pub const OGRErr_OGRERR_NONE: OGRErr = 1; +///
+pub type OGRErr = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/enum.rs b/bindgen-tests/tests/expectations/tests/enum.rs new file mode 100644 index 0000000000..820182125a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub member: foo__bindgen_ty_1, +} +pub const foo_FOO_A: foo__bindgen_ty_1 = 0; +pub const foo_FOO_B: foo__bindgen_ty_1 = 1; +pub type foo__bindgen_ty_1 = ::std::os::raw::c_uint; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::member"][::std::mem::offset_of!(foo, member) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const Foo_Bar: Foo = 0; +pub const Foo_Qux: Foo = 1; +pub type Foo = ::std::os::raw::c_uint; +pub const Neg_MinusOne: Neg = -1; +pub const Neg_One: Neg = 1; +pub type Neg = ::std::os::raw::c_int; +pub const NoDebug_NoDebug1: NoDebug = 0; +pub const NoDebug_NoDebug2: NoDebug = 1; +///
+pub type NoDebug = ::std::os::raw::c_uint; +pub const Debug_Debug1: Debug = 0; +pub const Debug_Debug2: Debug = 1; +///
+pub type Debug = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/enum_alias.rs b/bindgen-tests/tests/expectations/tests/enum_alias.rs new file mode 100644 index 0000000000..0d29768837 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_alias.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Bar { + VAL = 0, +} diff --git a/bindgen-tests/tests/expectations/tests/enum_and_vtable_mangling.rs b/bindgen-tests/tests/expectations/tests/enum_and_vtable_mangling.rs new file mode 100644 index 0000000000..0a7e16d6dd --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_and_vtable_mangling.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_; +pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + match_ = 0, + whatever_else = 1, +} +#[repr(C)] +pub struct C__bindgen_vtable { + pub C_match: unsafe extern "C" fn(this: *mut C), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub vtable_: *const C__bindgen_vtable, + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 16usize]; + ["Alignment of C"][::std::mem::align_of::() - 8usize]; + ["Offset of field: C::i"][::std::mem::offset_of!(C, i) - 8usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C5matchEv"] + pub fn C_match(this: *mut ::std::os::raw::c_void); +} diff --git a/bindgen-tests/tests/expectations/tests/enum_dupe.rs b/bindgen-tests/tests/expectations/tests/enum_dupe.rs new file mode 100644 index 0000000000..3ee4c68cbd --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_dupe.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl Foo { + pub const Dupe: Foo = Foo::Bar; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/enum_explicit_type.rs b/bindgen-tests/tests/expectations/tests/enum_explicit_type.rs new file mode 100644 index 0000000000..1f3dd36f96 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_explicit_type.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 0, + Qux = 1, +} +#[repr(i8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Neg { + MinusOne = -1, + One = 1, +} +#[repr(u16)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Bigger { + Much = 255, + Larger = 256, +} +#[repr(i64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MuchLong { + MuchLow = -4294967296, +} +#[repr(i64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MuchLongLong { + I64_MIN = -9223372036854775808, +} +#[repr(u64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MuchULongLong { + MuchHigh = 4294967296, +} +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum BoolEnumsAreFun { + Value = 1, +} +pub type MyType = bool; +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum BoolEnumsAreFun2 { + Value2 = 1, +} +pub const AnonymousVariantOne: _bindgen_ty_1 = _bindgen_ty_1::AnonymousVariantOne; +pub const AnonymousVariantTwo: _bindgen_ty_1 = _bindgen_ty_1::AnonymousVariantTwo; +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + AnonymousVariantOne = 0, + AnonymousVariantTwo = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/enum_explicit_type_constants.rs b/bindgen-tests/tests/expectations/tests/enum_explicit_type_constants.rs new file mode 100644 index 0000000000..8f310572b6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_explicit_type_constants.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(target_os = "windows"))] +pub const Foo_Bar: Foo = 0; +pub const Foo_Qux: Foo = 1; +pub type Foo = ::std::os::raw::c_uchar; +pub const Neg_MinusOne: Neg = -1; +pub const Neg_One: Neg = 1; +pub type Neg = ::std::os::raw::c_schar; +pub const Bigger_Much: Bigger = 255; +pub const Bigger_Larger: Bigger = 256; +pub type Bigger = ::std::os::raw::c_ushort; +pub const MuchLong_MuchLow: MuchLong = -4294967296; +pub type MuchLong = ::std::os::raw::c_long; +pub const MuchLongLong_I64_MIN: MuchLongLong = -9223372036854775808; +pub type MuchLongLong = ::std::os::raw::c_longlong; +pub const MuchULongLong_MuchHigh: MuchULongLong = 4294967296; +pub type MuchULongLong = ::std::os::raw::c_ulonglong; +pub const BoolEnumsAreFun_Value: BoolEnumsAreFun = true; +pub type BoolEnumsAreFun = bool; +pub type MyType = bool; +pub const BoolEnumsAreFun2_Value2: BoolEnumsAreFun2 = true; +pub type BoolEnumsAreFun2 = MyType; +pub const AnonymousVariantOne: _bindgen_ty_1 = 0; +pub const AnonymousVariantTwo: _bindgen_ty_1 = 1; +pub type _bindgen_ty_1 = ::std::os::raw::c_uchar; diff --git a/bindgen-tests/tests/expectations/tests/enum_in_template.rs b/bindgen-tests/tests/expectations/tests/enum_in_template.rs new file mode 100644 index 0000000000..e54a97b5f4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_in_template.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_Bar_A: Foo_Bar = 0; +pub const Foo_Bar_B: Foo_Bar = 0; +pub type Foo_Bar = i32; diff --git a/bindgen-tests/tests/expectations/tests/enum_in_template_with_typedef.rs b/bindgen-tests/tests/expectations/tests/enum_in_template_with_typedef.rs new file mode 100644 index 0000000000..b71923e10f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_in_template_with_typedef.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct std_fbstring_core { + pub _address: u8, +} +pub type std_fbstring_core_category_type = u8; +impl std_fbstring_core_Category { + pub const Bar: std_fbstring_core_Category = std_fbstring_core_Category::Foo; +} +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum std_fbstring_core_Category { + Foo = 0, +} diff --git a/bindgen-tests/tests/expectations/tests/enum_negative.rs b/bindgen-tests/tests/expectations/tests/enum_negative.rs new file mode 100644 index 0000000000..f946e0f044 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_negative.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = -2, + Qux = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/enum_packed.rs b/bindgen-tests/tests/expectations/tests/enum_packed.rs new file mode 100644 index 0000000000..d4ec2192d1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/enum_packed.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + Bar = 0, + Qux = 1, +} +#[repr(i8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Neg { + MinusOne = -1, + One = 1, +} +#[repr(u16)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Bigger { + Much = 255, + Larger = 256, +} diff --git a/bindgen-tests/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs b/bindgen-tests/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs new file mode 100644 index 0000000000..79004238fc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs @@ -0,0 +1,3 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![allow(overflowing_literals)] +pub const a: u32 = 4294967291; diff --git a/bindgen-tests/tests/expectations/tests/eval-value-dependent.rs b/bindgen-tests/tests/expectations/tests/eval-value-dependent.rs new file mode 100644 index 0000000000..b9b2709cfa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/eval-value-dependent.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct e { + pub _address: u8, +} +pub type e_f = d; diff --git a/tests/expectations/tests/eval-variadic-template-parameter.rs b/bindgen-tests/tests/expectations/tests/eval-variadic-template-parameter.rs similarity index 77% rename from tests/expectations/tests/eval-variadic-template-parameter.rs rename to bindgen-tests/tests/expectations/tests/eval-variadic-template-parameter.rs index 1386396f46..fccd2ad5d7 100644 --- a/tests/expectations/tests/eval-variadic-template-parameter.rs +++ b/bindgen-tests/tests/expectations/tests/eval-variadic-template-parameter.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct B { diff --git a/bindgen-tests/tests/expectations/tests/explicit-padding.rs b/bindgen-tests/tests/expectations/tests/explicit-padding.rs new file mode 100644 index 0000000000..ec21399106 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/explicit-padding.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct pad_me { + pub first: u8, + pub __bindgen_padding_0: [u8; 3usize], + pub second: u32, + pub third: u16, + pub __bindgen_padding_1: [u8; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of pad_me"][::std::mem::size_of::() - 12usize]; + ["Alignment of pad_me"][::std::mem::align_of::() - 4usize]; + ["Offset of field: pad_me::first"][::std::mem::offset_of!(pad_me, first) - 0usize]; + ["Offset of field: pad_me::second"][::std::mem::offset_of!(pad_me, second) - 4usize]; + ["Offset of field: pad_me::third"][::std::mem::offset_of!(pad_me, third) - 8usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub union dont_pad_me { + pub first: u8, + pub second: u32, + pub third: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of dont_pad_me"][::std::mem::size_of::() - 4usize]; + ["Alignment of dont_pad_me"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: dont_pad_me::first", + ][::std::mem::offset_of!(dont_pad_me, first) - 0usize]; + [ + "Offset of field: dont_pad_me::second", + ][::std::mem::offset_of!(dont_pad_me, second) - 0usize]; + [ + "Offset of field: dont_pad_me::third", + ][::std::mem::offset_of!(dont_pad_me, third) - 0usize]; +}; +impl Default for dont_pad_me { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/extern-const-struct.rs b/bindgen-tests/tests/expectations/tests/extern-const-struct.rs new file mode 100644 index 0000000000..7085bef5c8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern-const-struct.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsFoo { + pub details: [f32; 400usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsFoo"][::std::mem::size_of::() - 1600usize]; + ["Alignment of nsFoo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: nsFoo::details"][::std::mem::offset_of!(nsFoo, details) - 0usize]; +}; +impl Default for nsFoo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + pub static gDetails: nsFoo; +} diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs new file mode 100644 index 0000000000..5aa9e45ec2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-many.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(dead_code)] +#[cfg_attr(not(windows), link(wasm_import_module = "test-module"))] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs new file mode 100644 index 0000000000..388594b27e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs-wasm.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[link(wasm_import_module = "test-module")] +#[allow(dead_code)] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs new file mode 100644 index 0000000000..657cec106a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern-fn-block-attrs.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(dead_code)] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/expectations/tests/extern.rs b/bindgen-tests/tests/expectations/tests/extern.rs new file mode 100644 index 0000000000..496f595a0d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type foo = ::std::option::Option< + unsafe extern "C" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int, +>; diff --git a/bindgen-tests/tests/expectations/tests/extern_blocks_post_1_82.rs b/bindgen-tests/tests/expectations/tests/extern_blocks_post_1_82.rs new file mode 100644 index 0000000000..a322df78ce --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern_blocks_post_1_82.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn cool_function(i: ::std::os::raw::c_int, c: ::std::os::raw::c_char); +} +unsafe extern "C" { + pub static mut cool_static: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/extern_blocks_pre_1_82.rs b/bindgen-tests/tests/expectations/tests/extern_blocks_pre_1_82.rs new file mode 100644 index 0000000000..a322df78ce --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/extern_blocks_pre_1_82.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn cool_function(i: ::std::os::raw::c_int, c: ::std::os::raw::c_char); +} +unsafe extern "C" { + pub static mut cool_static: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs b/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs new file mode 100644 index 0000000000..99ca3d4b9b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs @@ -0,0 +1,264 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct my_struct { + pub a: ::std::os::raw::c_int, + private_b: ::std::os::raw::c_int, + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of my_struct"][::std::mem::size_of::() - 12usize]; + ["Alignment of my_struct"][::std::mem::align_of::() - 4usize]; + ["Offset of field: my_struct::a"][::std::mem::offset_of!(my_struct, a) - 0usize]; + [ + "Offset of field: my_struct::private_b", + ][::std::mem::offset_of!(my_struct, private_b) - 4usize]; +}; +impl my_struct { + #[inline] + pub fn c(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn c_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_c_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn private_d(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + fn set_private_d(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + unsafe fn private_d_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_private_d_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + c: ::std::os::raw::c_int, + private_d: ::std::os::raw::c_int, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let c: u32 = unsafe { ::std::mem::transmute(c) }; + c as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let private_d: u32 = unsafe { ::std::mem::transmute(private_d) }; + private_d as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/field-visibility.rs b/bindgen-tests/tests/expectations/tests/field-visibility.rs new file mode 100644 index 0000000000..13a1d9a543 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/field-visibility.rs @@ -0,0 +1,277 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct my_struct1 { + pub _bindgen_align: [u32; 0], + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of my_struct1"][::std::mem::size_of::() - 4usize]; + ["Alignment of my_struct1"][::std::mem::align_of::() - 4usize]; +}; +impl my_struct1 { + #[inline] + fn a(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + fn set_a(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1(a: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u32 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct my_struct2 { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of my_struct2"][::std::mem::size_of::() - 4usize]; + ["Alignment of my_struct2"][::std::mem::align_of::() - 4usize]; +}; +impl my_struct2 { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_int, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u32 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/fit-macro-constant-types-signed.rs b/bindgen-tests/tests/expectations/tests/fit-macro-constant-types-signed.rs new file mode 100644 index 0000000000..d4ad5e0fcc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/fit-macro-constant-types-signed.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const N0: i8 = 0; +pub const N1: i8 = 1; +pub const N2: i8 = 2; +pub const N_1: i8 = -1; +pub const N_2: i8 = -2; +pub const MAX_U16: i32 = 65535; +pub const MAX_I16: i16 = 32767; +pub const MAX_I16_Plus1: i32 = 32768; +pub const MAX_U16_Plus1: i32 = 65536; +pub const MAX_I16_Minus1: i16 = 32766; +pub const MAX_U16_Minus1: i32 = 65534; +pub const MIN_U16: i8 = 0; +pub const MIN_I16: i16 = -32768; +pub const MIN_U16_Plus1: i8 = 1; +pub const MIN_I16_Plus1: i16 = -32767; +pub const MIN_U16_Minus1: i8 = -1; +pub const MIN_I16_Minus1: i32 = -32769; +pub const MAX_U32: i64 = 4294967295; +pub const MAX_I32: i32 = 2147483647; +pub const MAX_I32_Plus1: i64 = 2147483648; +pub const MAX_U32_Plus1: i64 = 4294967296; +pub const MAX_I32_Minus1: i32 = 2147483646; +pub const MAX_U32_Minus1: i64 = 4294967294; +pub const MIN_U32: i8 = 0; +pub const MIN_I32: i32 = -2147483648; +pub const MIN_U32_Plus1: i8 = 1; +pub const MIN_I32_Plus1: i32 = -2147483647; +pub const MIN_U32_Minus1: i8 = -1; +pub const MIN_I32_Minus1: i64 = -2147483649; +pub const LONG12: i64 = 123456789012; +pub const LONG_12: i64 = -123456789012; +unsafe extern "C" { + pub fn foo( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_uint, + arg4: ::std::os::raw::c_char, + arg5: ::std::os::raw::c_uchar, + arg6: ::std::os::raw::c_schar, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar( + arg1: ::std::os::raw::c_long, + arg2: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_long; +} diff --git a/bindgen-tests/tests/expectations/tests/fit-macro-constant-types.rs b/bindgen-tests/tests/expectations/tests/fit-macro-constant-types.rs new file mode 100644 index 0000000000..5542a645da --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/fit-macro-constant-types.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const N0: u8 = 0; +pub const N1: u8 = 1; +pub const N2: u8 = 2; +pub const N_1: i8 = -1; +pub const N_2: i8 = -2; +pub const MAX_U16: u16 = 65535; +pub const MAX_I16: u16 = 32767; +pub const MAX_I16_Plus1: u16 = 32768; +pub const MAX_U16_Plus1: u32 = 65536; +pub const MAX_I16_Minus1: u16 = 32766; +pub const MAX_U16_Minus1: u16 = 65534; +pub const MIN_U16: u8 = 0; +pub const MIN_I16: i16 = -32768; +pub const MIN_U16_Plus1: u8 = 1; +pub const MIN_I16_Plus1: i16 = -32767; +pub const MIN_U16_Minus1: i8 = -1; +pub const MIN_I16_Minus1: i32 = -32769; +pub const MAX_U32: u32 = 4294967295; +pub const MAX_I32: u32 = 2147483647; +pub const MAX_I32_Plus1: u32 = 2147483648; +pub const MAX_U32_Plus1: u64 = 4294967296; +pub const MAX_I32_Minus1: u32 = 2147483646; +pub const MAX_U32_Minus1: u32 = 4294967294; +pub const MIN_U32: u8 = 0; +pub const MIN_I32: i32 = -2147483648; +pub const MIN_U32_Plus1: u8 = 1; +pub const MIN_I32_Plus1: i32 = -2147483647; +pub const MIN_U32_Minus1: i8 = -1; +pub const MIN_I32_Minus1: i64 = -2147483649; +pub const LONG12: u64 = 123456789012; +pub const LONG_12: i64 = -123456789012; +unsafe extern "C" { + pub fn foo( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_uint, + arg4: ::std::os::raw::c_char, + arg5: ::std::os::raw::c_uchar, + arg6: ::std::os::raw::c_schar, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar( + arg1: ::std::os::raw::c_long, + arg2: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_long; +} diff --git a/bindgen-tests/tests/expectations/tests/flexarray.rs b/bindgen-tests/tests/expectations/tests/flexarray.rs new file mode 100644 index 0000000000..b9c800366e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/flexarray.rs @@ -0,0 +1,555 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#![feature(ptr_metadata, layout_for_ptr)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct flexarray { + pub count: ::std::os::raw::c_int, + pub data: FAM, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of flexarray"][::std::mem::size_of::() - 4usize]; + ["Alignment of flexarray"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: flexarray::count", + ][::std::mem::offset_of!(flexarray, count) - 0usize]; + [ + "Offset of field: flexarray::data", + ][::std::mem::offset_of!(flexarray, data) - 4usize]; +}; +impl flexarray<[::std::os::raw::c_int]> { + pub fn layout(len: usize) -> ::std::alloc::Layout { + unsafe { + let p: *const Self = ::std::ptr::from_raw_parts( + ::std::ptr::null::<()>(), + len, + ); + ::std::alloc::Layout::for_value_raw(p) + } + } + #[inline] + pub fn fixed(&self) -> (&flexarray<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + (&*(ptr as *const flexarray<[::std::os::raw::c_int; 0]>), len) + } + } + #[inline] + pub fn fixed_mut(&mut self) -> (&mut flexarray<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + (&mut *(ptr as *mut flexarray<[::std::os::raw::c_int; 0]>), len) + } + } +} +impl flexarray<[::std::os::raw::c_int; 0]> { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref(&self, len: usize) -> &flexarray<[::std::os::raw::c_int]> { + Self::flex_ptr(self, len) + } + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut( + &mut self, + len: usize, + ) -> &mut flexarray<[::std::os::raw::c_int]> { + Self::flex_ptr_mut(self, len).assume_init() + } + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>( + ptr: *const Self, + len: usize, + ) -> &'unbounded flexarray<[::std::os::raw::c_int]> { + &*::std::ptr::from_raw_parts(ptr as *const (), len) + } + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::std::mem::MaybeUninit<&'unbounded mut flexarray<[::std::os::raw::c_int]>> { + let mut uninit = ::std::mem::MaybeUninit::< + &mut flexarray<[::std::os::raw::c_int]>, + >::uninit(); + (uninit.as_mut_ptr() as *mut *mut flexarray<[::std::os::raw::c_int]>) + .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len)); + uninit + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct flexarray_zero { + pub count: ::std::os::raw::c_int, + pub data: FAM, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of flexarray_zero"][::std::mem::size_of::() - 4usize]; + ["Alignment of flexarray_zero"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: flexarray_zero::count", + ][::std::mem::offset_of!(flexarray_zero, count) - 0usize]; + [ + "Offset of field: flexarray_zero::data", + ][::std::mem::offset_of!(flexarray_zero, data) - 4usize]; +}; +impl flexarray_zero<[::std::os::raw::c_int]> { + pub fn layout(len: usize) -> ::std::alloc::Layout { + unsafe { + let p: *const Self = ::std::ptr::from_raw_parts( + ::std::ptr::null::<()>(), + len, + ); + ::std::alloc::Layout::for_value_raw(p) + } + } + #[inline] + pub fn fixed(&self) -> (&flexarray_zero<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + (&*(ptr as *const flexarray_zero<[::std::os::raw::c_int; 0]>), len) + } + } + #[inline] + pub fn fixed_mut( + &mut self, + ) -> (&mut flexarray_zero<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + (&mut *(ptr as *mut flexarray_zero<[::std::os::raw::c_int; 0]>), len) + } + } +} +impl flexarray_zero<[::std::os::raw::c_int; 0]> { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref( + &self, + len: usize, + ) -> &flexarray_zero<[::std::os::raw::c_int]> { + Self::flex_ptr(self, len) + } + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut( + &mut self, + len: usize, + ) -> &mut flexarray_zero<[::std::os::raw::c_int]> { + Self::flex_ptr_mut(self, len).assume_init() + } + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>( + ptr: *const Self, + len: usize, + ) -> &'unbounded flexarray_zero<[::std::os::raw::c_int]> { + &*::std::ptr::from_raw_parts(ptr as *const (), len) + } + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::std::mem::MaybeUninit< + &'unbounded mut flexarray_zero<[::std::os::raw::c_int]>, + > { + let mut uninit = ::std::mem::MaybeUninit::< + &mut flexarray_zero<[::std::os::raw::c_int]>, + >::uninit(); + (uninit.as_mut_ptr() as *mut *mut flexarray_zero<[::std::os::raw::c_int]>) + .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len)); + uninit + } +} +#[repr(C)] +#[derive(Debug)] +pub struct flexarray_template { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub count: ::std::os::raw::c_int, + pub data: FAM, +} +impl flexarray_template { + pub fn layout(len: usize) -> ::std::alloc::Layout { + unsafe { + let p: *const Self = ::std::ptr::from_raw_parts( + ::std::ptr::null::<()>(), + len, + ); + ::std::alloc::Layout::for_value_raw(p) + } + } + #[inline] + pub fn fixed(&self) -> (&flexarray_template, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + (&*(ptr as *const flexarray_template), len) + } + } + #[inline] + pub fn fixed_mut(&mut self) -> (&mut flexarray_template, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + (&mut *(ptr as *mut flexarray_template), len) + } + } +} +impl flexarray_template { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref(&self, len: usize) -> &flexarray_template { + Self::flex_ptr(self, len) + } + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut( + &mut self, + len: usize, + ) -> &mut flexarray_template { + Self::flex_ptr_mut(self, len).assume_init() + } + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>( + ptr: *const Self, + len: usize, + ) -> &'unbounded flexarray_template { + &*::std::ptr::from_raw_parts(ptr as *const (), len) + } + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::std::mem::MaybeUninit<&'unbounded mut flexarray_template> { + let mut uninit = ::std::mem::MaybeUninit::< + &mut flexarray_template, + >::uninit(); + (uninit.as_mut_ptr() as *mut *mut flexarray_template) + .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len)); + uninit + } +} +impl Default for flexarray_template { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct flexarray_ref { + pub things: *mut flexarray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of flexarray_ref"][::std::mem::size_of::() - 8usize]; + ["Alignment of flexarray_ref"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: flexarray_ref::things", + ][::std::mem::offset_of!(flexarray_ref, things) - 0usize]; +}; +impl Default for flexarray_ref { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct flexarray_bogus_zero_fam { + pub count: ::std::os::raw::c_int, + pub data1: __IncompleteArrayField<::std::os::raw::c_int>, + pub data2: FAM, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of flexarray_bogus_zero_fam", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of flexarray_bogus_zero_fam", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: flexarray_bogus_zero_fam::count", + ][::std::mem::offset_of!(flexarray_bogus_zero_fam, count) - 0usize]; + [ + "Offset of field: flexarray_bogus_zero_fam::data1", + ][::std::mem::offset_of!(flexarray_bogus_zero_fam, data1) - 4usize]; + [ + "Offset of field: flexarray_bogus_zero_fam::data2", + ][::std::mem::offset_of!(flexarray_bogus_zero_fam, data2) - 4usize]; +}; +impl flexarray_bogus_zero_fam<[::std::os::raw::c_char]> { + pub fn layout(len: usize) -> ::std::alloc::Layout { + unsafe { + let p: *const Self = ::std::ptr::from_raw_parts( + ::std::ptr::null::<()>(), + len, + ); + ::std::alloc::Layout::for_value_raw(p) + } + } + #[inline] + pub fn fixed( + &self, + ) -> (&flexarray_bogus_zero_fam<[::std::os::raw::c_char; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + ( + &*(ptr as *const flexarray_bogus_zero_fam<[::std::os::raw::c_char; 0]>), + len, + ) + } + } + #[inline] + pub fn fixed_mut( + &mut self, + ) -> (&mut flexarray_bogus_zero_fam<[::std::os::raw::c_char; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + ( + &mut *(ptr + as *mut flexarray_bogus_zero_fam<[::std::os::raw::c_char; 0]>), + len, + ) + } + } +} +impl flexarray_bogus_zero_fam<[::std::os::raw::c_char; 0]> { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref( + &self, + len: usize, + ) -> &flexarray_bogus_zero_fam<[::std::os::raw::c_char]> { + Self::flex_ptr(self, len) + } + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut( + &mut self, + len: usize, + ) -> &mut flexarray_bogus_zero_fam<[::std::os::raw::c_char]> { + Self::flex_ptr_mut(self, len).assume_init() + } + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>( + ptr: *const Self, + len: usize, + ) -> &'unbounded flexarray_bogus_zero_fam<[::std::os::raw::c_char]> { + &*::std::ptr::from_raw_parts(ptr as *const (), len) + } + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::std::mem::MaybeUninit< + &'unbounded mut flexarray_bogus_zero_fam<[::std::os::raw::c_char]>, + > { + let mut uninit = ::std::mem::MaybeUninit::< + &mut flexarray_bogus_zero_fam<[::std::os::raw::c_char]>, + >::uninit(); + (uninit.as_mut_ptr() + as *mut *mut flexarray_bogus_zero_fam<[::std::os::raw::c_char]>) + .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len)); + uninit + } +} +#[repr(C)] +#[repr(align(128))] +#[derive(Debug)] +pub struct flexarray_align { + pub count: ::std::os::raw::c_int, + pub data: FAM, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of flexarray_align"][::std::mem::size_of::() - 128usize]; + [ + "Alignment of flexarray_align", + ][::std::mem::align_of::() - 128usize]; + [ + "Offset of field: flexarray_align::count", + ][::std::mem::offset_of!(flexarray_align, count) - 0usize]; + [ + "Offset of field: flexarray_align::data", + ][::std::mem::offset_of!(flexarray_align, data) - 4usize]; +}; +impl flexarray_align<[::std::os::raw::c_int]> { + pub fn layout(len: usize) -> ::std::alloc::Layout { + unsafe { + let p: *const Self = ::std::ptr::from_raw_parts( + ::std::ptr::null::<()>(), + len, + ); + ::std::alloc::Layout::for_value_raw(p) + } + } + #[inline] + pub fn fixed(&self) -> (&flexarray_align<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + (&*(ptr as *const flexarray_align<[::std::os::raw::c_int; 0]>), len) + } + } + #[inline] + pub fn fixed_mut( + &mut self, + ) -> (&mut flexarray_align<[::std::os::raw::c_int; 0]>, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + (&mut *(ptr as *mut flexarray_align<[::std::os::raw::c_int; 0]>), len) + } + } +} +impl flexarray_align<[::std::os::raw::c_int; 0]> { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref( + &self, + len: usize, + ) -> &flexarray_align<[::std::os::raw::c_int]> { + Self::flex_ptr(self, len) + } + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut( + &mut self, + len: usize, + ) -> &mut flexarray_align<[::std::os::raw::c_int]> { + Self::flex_ptr_mut(self, len).assume_init() + } + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>( + ptr: *const Self, + len: usize, + ) -> &'unbounded flexarray_align<[::std::os::raw::c_int]> { + &*::std::ptr::from_raw_parts(ptr as *const (), len) + } + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::std::mem::MaybeUninit< + &'unbounded mut flexarray_align<[::std::os::raw::c_int]>, + > { + let mut uninit = ::std::mem::MaybeUninit::< + &mut flexarray_align<[::std::os::raw::c_int]>, + >::uninit(); + (uninit.as_mut_ptr() as *mut *mut flexarray_align<[::std::os::raw::c_int]>) + .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len)); + uninit + } +} +impl Default for flexarray_align<[::std::os::raw::c_int; 0]> { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/float128.rs b/bindgen-tests/tests/expectations/tests/float128.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/float128.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/float16.rs b/bindgen-tests/tests/expectations/tests/float16.rs new file mode 100644 index 0000000000..2066b71801 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/float16.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(transparent)] +pub struct __BindgenFloat16(pub u16); +unsafe extern "C" { + pub static mut global: __BindgenFloat16; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct Test__Float16 { + pub f: __BindgenFloat16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test__Float16"][::std::mem::size_of::() - 2usize]; + ["Alignment of Test__Float16"][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: Test__Float16::f", + ][::std::mem::offset_of!(Test__Float16, f) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Test__Float16Ref { + pub f: *mut __BindgenFloat16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test__Float16Ref"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of Test__Float16Ref", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: Test__Float16Ref::f", + ][::std::mem::offset_of!(Test__Float16Ref, f) - 0usize]; +}; +impl Default for Test__Float16Ref { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/forward-declaration-autoptr.rs b/bindgen-tests/tests/expectations/tests/forward-declaration-autoptr.rs new file mode 100644 index 0000000000..b74b408841 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward-declaration-autoptr.rs @@ -0,0 +1,50 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RefPtr { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_inner: *mut T, +} +impl Default for RefPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub m_member: RefPtr, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::m_member"][::std::mem::offset_of!(Bar, m_member) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: RefPtr_open0_Foo_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: RefPtr_open0_Foo_close0", + ][::std::mem::align_of::>() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/forward-enum-decl.rs b/bindgen-tests/tests/expectations/tests/forward-enum-decl.rs new file mode 100644 index 0000000000..9949b39aae --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward-enum-decl.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum CSSPseudoClassType { + empty = 0, + link = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/forward-inherit-struct-with-fields.rs b/bindgen-tests/tests/expectations/tests/forward-inherit-struct-with-fields.rs new file mode 100644 index 0000000000..069c76fead --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward-inherit-struct-with-fields.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct js_RootedBase { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub foo: *mut T, + pub next: *mut Rooted, +} +impl Default for js_RootedBase { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: js_RootedBase, +} +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/forward-inherit-struct.rs b/bindgen-tests/tests/expectations/tests/forward-inherit-struct.rs new file mode 100644 index 0000000000..52888c4626 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward-inherit-struct.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct js_RootedBase { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _address: u8, +} +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/forward_declared_complex_types.rs b/bindgen-tests/tests/expectations/tests/forward_declared_complex_types.rs new file mode 100644 index 0000000000..79554d58e4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward_declared_complex_types.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo_empty { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo_empty"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo_empty"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub f: *mut Foo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::f"][::std::mem::offset_of!(Bar, f) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z10baz_structP3Foo"] + pub fn baz_struct(f: *mut Foo); +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Union { + _unused: [u8; 0], +} +unsafe extern "C" { + #[link_name = "\u{1}_Z9baz_unionP5Union"] + pub fn baz_union(u: *mut Union); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Quux { + _unused: [u8; 0], +} +unsafe extern "C" { + #[link_name = "\u{1}_Z9baz_classP4Quux"] + pub fn baz_class(q: *mut Quux); +} diff --git a/bindgen-tests/tests/expectations/tests/forward_declared_opaque.rs b/bindgen-tests/tests/expectations/tests/forward_declared_opaque.rs new file mode 100644 index 0000000000..1f92194045 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward_declared_opaque.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct a { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct b { + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/expectations/tests/forward_declared_struct.rs b/bindgen-tests/tests/expectations/tests/forward_declared_struct.rs new file mode 100644 index 0000000000..1f6dfd0f58 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/forward_declared_struct.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct a { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of a"][::std::mem::size_of::
() - 4usize]; + ["Alignment of a"][::std::mem::align_of::() - 4usize]; + ["Offset of field: a::b"][::std::mem::offset_of!(a, b) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct c { + pub d: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of c"][::std::mem::size_of::() - 4usize]; + ["Alignment of c"][::std::mem::align_of::() - 4usize]; + ["Offset of field: c::d"][::std::mem::offset_of!(c, d) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/func_proto.rs b/bindgen-tests/tests/expectations/tests/func_proto.rs new file mode 100644 index 0000000000..496f595a0d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_proto.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type foo = ::std::option::Option< + unsafe extern "C" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int, +>; diff --git a/bindgen-tests/tests/expectations/tests/func_ptr.rs b/bindgen-tests/tests/expectations/tests/func_ptr.rs new file mode 100644 index 0000000000..b91bdba872 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_ptr.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut foo: ::std::option::Option< + unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >; +} diff --git a/bindgen-tests/tests/expectations/tests/func_ptr_in_struct.rs b/bindgen-tests/tests/expectations/tests/func_ptr_in_struct.rs new file mode 100644 index 0000000000..308bb069e0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_ptr_in_struct.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum baz { + __bindgen_cannot_repr_c_on_empty_enum = 0, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo { + pub bar: ::std::option::Option< + unsafe extern "C" fn(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) -> baz, + >, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/func_ptr_return_type.rs b/bindgen-tests/tests/expectations/tests/func_ptr_return_type.rs new file mode 100644 index 0000000000..504eefdfb1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_ptr_return_type.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn func() -> ::std::option::Option< + unsafe extern "C" fn( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >; +} diff --git a/bindgen-tests/tests/expectations/tests/func_return_must_use.rs b/bindgen-tests/tests/expectations/tests/func_return_must_use.rs new file mode 100644 index 0000000000..904c71cbe3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_return_must_use.rs @@ -0,0 +1,56 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type MustUseInt = ::std::os::raw::c_int; +unsafe extern "C" { + #[must_use] + pub fn return_int() -> MustUseInt; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[must_use] +pub struct MustUseStruct { + _unused: [u8; 0], +} +unsafe extern "C" { + #[must_use] + pub fn return_struct() -> MustUseStruct; +} +///
+pub type AnnotatedInt = ::std::os::raw::c_int; +unsafe extern "C" { + #[must_use] + pub fn return_annotated_int() -> AnnotatedInt; +} +unsafe extern "C" { + pub fn return_plain_int() -> ::std::os::raw::c_int; +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +#[must_use] +pub struct AnnotatedStruct {} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AnnotatedStruct"][::std::mem::size_of::() - 0usize]; + ["Alignment of AnnotatedStruct"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[must_use] + pub fn return_annotated_struct() -> AnnotatedStruct; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PlainStruct {} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PlainStruct"][::std::mem::size_of::() - 0usize]; + ["Alignment of PlainStruct"][::std::mem::align_of::() - 1usize]; +}; +///
+pub type TypedefPlainStruct = PlainStruct; +unsafe extern "C" { + pub fn return_plain_struct() -> PlainStruct; +} +unsafe extern "C" { + #[must_use] + pub fn return_typedef_struct() -> TypedefPlainStruct; +} diff --git a/bindgen-tests/tests/expectations/tests/func_with_array_arg.rs b/bindgen-tests/tests/expectations/tests/func_with_array_arg.rs new file mode 100644 index 0000000000..20bdc4ac27 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_with_array_arg.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn f(x: *mut ::std::os::raw::c_int); +} diff --git a/bindgen-tests/tests/expectations/tests/func_with_func_ptr_arg.rs b/bindgen-tests/tests/expectations/tests/func_with_func_ptr_arg.rs new file mode 100644 index 0000000000..56cf40fb59 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/func_with_func_ptr_arg.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(bar: ::std::option::Option); +} +unsafe extern "C" { + pub fn bar( + one: ::std::option::Option< + unsafe extern "C" fn(a: ::std::os::raw::c_int, b: ::std::os::raw::c_int), + >, + two: ::std::option::Option< + unsafe extern "C" fn(c: ::std::os::raw::c_int, d: ::std::os::raw::c_int), + >, + ); +} diff --git a/bindgen-tests/tests/expectations/tests/function-typedef-stdcall.rs b/bindgen-tests/tests/expectations/tests/function-typedef-stdcall.rs new file mode 100644 index 0000000000..3b08e0988c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/function-typedef-stdcall.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type PFN_VIGEM_X360_NOTIFICATION = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_void, + arg2: *mut ::std::os::raw::c_void, + arg3: ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_uchar, + arg5: ::std::os::raw::c_uchar, + arg6: *mut ::std::os::raw::c_void, + ), +>; diff --git a/bindgen-tests/tests/expectations/tests/gen-constructors-neg.rs b/bindgen-tests/tests/expectations/tests/gen-constructors-neg.rs new file mode 100644 index 0000000000..551dff82cf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/gen-constructors-neg.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/gen-constructors.rs b/bindgen-tests/tests/expectations/tests/gen-constructors.rs new file mode 100644 index 0000000000..80e6a25d70 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/gen-constructors.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3FooC1Ei"] + pub fn Foo_Foo(this: *mut Foo, a: ::std::os::raw::c_int); +} +impl Foo { + #[inline] + pub unsafe fn new(a: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + Foo_Foo(__bindgen_tmp.as_mut_ptr(), a); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/gen-destructors-neg.rs b/bindgen-tests/tests/expectations/tests/gen-destructors-neg.rs new file mode 100644 index 0000000000..77b6a07bb1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/gen-destructors-neg.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct Foo { + pub bar: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/gen-destructors.rs b/bindgen-tests/tests/expectations/tests/gen-destructors.rs new file mode 100644 index 0000000000..c860c9985f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/gen-destructors.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct Foo { + pub bar: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3FooD1Ev"] + pub fn Foo_Foo_destructor(this: *mut Foo); +} +impl Foo { + #[inline] + pub unsafe fn destruct(&mut self) { + Foo_Foo_destructor(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/generate-inline.rs b/bindgen-tests/tests/expectations/tests/generate-inline.rs new file mode 100644 index 0000000000..c100f3936c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/generate-inline.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo3barEv"] + pub fn Foo_bar() -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn bar() -> ::std::os::raw::c_int { + Foo_bar() + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/generated/README.md b/bindgen-tests/tests/expectations/tests/generated/README.md new file mode 100644 index 0000000000..b4e8cabbf6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/generated/README.md @@ -0,0 +1,4 @@ +# Generated C, C++, Header files + +This directory contains files for features where extra files are generated +as a part of the feature. For example, `--wrap-static-fns`. diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c new file mode 100644 index 0000000000..a8fd5045d2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c @@ -0,0 +1,32 @@ +#include "tests/headers/wrap-static-fns.h" + +// Static wrappers + +int foo__extern(void) { return foo(); } +int bar__extern(void) { return bar(); } +int takes_ptr__extern(int *arg) { return takes_ptr(arg); } +int takes_fn_ptr__extern(int (*f) (int)) { return takes_fn_ptr(f); } +int takes_fn__extern(int (f) (int)) { return takes_fn(f); } +int takes_alias__extern(func f) { return takes_alias(f); } +int takes_qualified__extern(const int *const *arg) { return takes_qualified(arg); } +enum foo takes_enum__extern(const enum foo f) { return takes_enum(f); } +void nevermore__extern(void) { nevermore(); } +int takes_fn_with_no_args__extern(int (f) (void)) { return takes_fn_with_no_args(f); } +void no_extra_argument__extern(__builtin_va_list va) { no_extra_argument(va); } +int many_va_list__extern(int i, __builtin_va_list va1, __builtin_va_list va2) { return many_va_list(i, va1, va2); } +int wrap_as_variadic_fn1__extern(int i, ...) { + int ret; + va_list ap; + + va_start(ap, i); + ret = wrap_as_variadic_fn1(i, ap); + va_end(ap); + return ret; +} +void wrap_as_variadic_fn2__extern(int i, ...) { + va_list ap; + + va_start(ap, i); + wrap_as_variadic_fn2(i, ap); + va_end(ap); +} diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_aarch64_linux.c b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_aarch64_linux.c new file mode 100644 index 0000000000..a4269d8505 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_aarch64_linux.c @@ -0,0 +1,14 @@ +#include "tests/headers/wrap-static-fns.h" + +// Static wrappers + +int foo__extern(void) { return foo(); } +int bar__extern(void) { return bar(); } +int takes_ptr__extern(int *arg) { return takes_ptr(arg); } +int takes_fn_ptr__extern(int (*f) (int)) { return takes_fn_ptr(f); } +int takes_fn__extern(int (f) (int)) { return takes_fn(f); } +int takes_alias__extern(func f) { return takes_alias(f); } +int takes_qualified__extern(const int *const *arg) { return takes_qualified(arg); } +enum foo takes_enum__extern(const enum foo f) { return takes_enum(f); } +void nevermore__extern(void) { nevermore(); } +int takes_fn_with_no_args__extern(int (f) (void)) { return takes_fn_with_no_args(f); } diff --git a/bindgen-tests/tests/expectations/tests/i128.rs b/bindgen-tests/tests/expectations/tests/i128.rs new file mode 100644 index 0000000000..e29db491fe --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/i128.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub my_signed: i128, + pub my_unsigned: u128, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 32usize]; + ["Alignment of foo"][::std::mem::align_of::() - 16usize]; + ["Offset of field: foo::my_signed"][::std::mem::offset_of!(foo, my_signed) - 0usize]; + [ + "Offset of field: foo::my_unsigned", + ][::std::mem::offset_of!(foo, my_unsigned) - 16usize]; +}; diff --git a/tests/expectations/tests/in_class_typedef.rs b/bindgen-tests/tests/expectations/tests/in_class_typedef.rs similarity index 88% rename from tests/expectations/tests/in_class_typedef.rs rename to bindgen-tests/tests/expectations/tests/in_class_typedef.rs index 92a23ad31c..ccb73520d7 100644 --- a/tests/expectations/tests/in_class_typedef.rs +++ b/bindgen-tests/tests/expectations/tests/in_class_typedef.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Foo { diff --git a/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs b/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs new file mode 100644 index 0000000000..a90fe54bf3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs @@ -0,0 +1,251 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug)] +pub struct foo { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub b: __IncompleteArrayField<*mut ::std::os::raw::c_void>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: foo::b"][::std::mem::offset_of!(foo, b) - 8usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl foo { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_char { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_char { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_char) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_char, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/infinite-macro.rs b/bindgen-tests/tests/expectations/tests/infinite-macro.rs new file mode 100644 index 0000000000..cf2b32f0ed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/infinite-macro.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const INFINITY: f64 = f64::INFINITY as _; +pub const NEG_INFINITY: f64 = f64::NEG_INFINITY as _; +pub const NAN: f64 = f64::NAN as _; +pub const F32_INFINITY: f32 = f64::INFINITY as _; +pub const F32_NEG_INFINITY: f32 = f64::NEG_INFINITY as _; +pub const F32_NAN: f32 = f64::NAN as _; diff --git a/bindgen-tests/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs b/bindgen-tests/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs new file mode 100644 index 0000000000..59e35f7b6c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs @@ -0,0 +1,169 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct BaseWithVtable__bindgen_vtable {} +/// This should have an explicit vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct BaseWithVtable { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub vtable_: *const BaseWithVtable__bindgen_vtable, + pub t: T, +} +impl Default for BaseWithVtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// This should not have an explicit vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DerivedWithNoVirtualMethods { + pub _base: BaseWithVtable<*mut ::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of DerivedWithNoVirtualMethods", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of DerivedWithNoVirtualMethods", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for DerivedWithNoVirtualMethods { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// This should not have an explicit vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DerivedWithVirtualMethods { + pub _base: BaseWithVtable<*mut ::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of DerivedWithVirtualMethods", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of DerivedWithVirtualMethods", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for DerivedWithVirtualMethods { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// This should not have any vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct BaseWithoutVtable { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub u: U, +} +impl Default for BaseWithoutVtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct DerivedWithVtable__bindgen_vtable(::std::os::raw::c_void); +/// This should have an explicit vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DerivedWithVtable { + pub vtable_: *const DerivedWithVtable__bindgen_vtable, + pub _base: BaseWithoutVtable<*mut ::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of DerivedWithVtable"][::std::mem::size_of::() - 16usize]; + [ + "Alignment of DerivedWithVtable", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for DerivedWithVtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// This should not have any vtable. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DerivedWithoutVtable { + pub _base: BaseWithoutVtable<*mut ::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of DerivedWithoutVtable", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of DerivedWithoutVtable", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for DerivedWithoutVtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: BaseWithVtable_open0_ptr_char_close0", + ][::std::mem::size_of::>() - 16usize]; + [ + "Align of template specialization: BaseWithVtable_open0_ptr_char_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: BaseWithVtable_open0_ptr_char_close0", + ][::std::mem::size_of::>() - 16usize]; + [ + "Align of template specialization: BaseWithVtable_open0_ptr_char_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: BaseWithoutVtable_open0_ptr_char_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: BaseWithoutVtable_open0_ptr_char_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: BaseWithoutVtable_open0_ptr_char_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: BaseWithoutVtable_open0_ptr_char_close0", + ][::std::mem::align_of::>() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/inherit-namespaced.rs b/bindgen-tests/tests/expectations/tests/inherit-namespaced.rs new file mode 100644 index 0000000000..52888c4626 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inherit-namespaced.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct js_RootedBase { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _address: u8, +} +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs b/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs new file mode 100644 index 0000000000..da9e519156 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs @@ -0,0 +1,69 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct A__bindgen_vtable {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct A { + pub vtable_: *const A__bindgen_vtable, + pub member: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::
() - 16usize]; + ["Alignment of A"][::std::mem::align_of::() - 8usize]; + ["Offset of field: A::member"][::std::mem::offset_of!(A, member) - 8usize]; +}; +impl Default for A { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct B__bindgen_vtable {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct B { + pub vtable_: *const B__bindgen_vtable, + pub member2: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 16usize]; + ["Alignment of B"][::std::mem::align_of::() - 8usize]; + ["Offset of field: B::member2"][::std::mem::offset_of!(B, member2) - 8usize]; +}; +impl Default for B { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub _base: A, + pub _base_1: B, + pub member3: f32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 40usize]; + ["Alignment of C"][::std::mem::align_of::() - 8usize]; + ["Offset of field: C::member3"][::std::mem::offset_of!(C, member3) - 32usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/inherit_named.rs b/bindgen-tests/tests/expectations/tests/inherit_named.rs new file mode 100644 index 0000000000..a371249ab0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inherit_named.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Wohoo { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Weeee { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: T, +} +impl Default for Weeee { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/inherit_typedef.rs b/bindgen-tests/tests/expectations/tests/inherit_typedef.rs new file mode 100644 index 0000000000..92320f45ef --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inherit_typedef.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +pub type TypedefedFoo = Foo; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/inline-function.rs b/bindgen-tests/tests/expectations/tests/inline-function.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline-function.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace.rs b/bindgen-tests/tests/expectations/tests/inline_namespace.rs new file mode 100644 index 0000000000..df05ab7b9d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + pub type Ty = ::std::os::raw::c_int; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar { + pub baz: root::foo::Ty, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::baz"][::std::mem::offset_of!(Bar, baz) - 0usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace_allowlist.rs b/bindgen-tests/tests/expectations/tests/inline_namespace_allowlist.rs new file mode 100644 index 0000000000..915a40c654 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace_allowlist.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod std { + #[allow(unused_imports)] + use self::super::super::root; + pub type string = *const ::std::os::raw::c_char; + } +} diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace_conservative.rs b/bindgen-tests/tests/expectations/tests/inline_namespace_conservative.rs new file mode 100644 index 0000000000..6941e74adb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace_conservative.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + pub mod bar { + #[allow(unused_imports)] + use self::super::super::super::root; + pub type Ty = ::std::os::raw::c_int; + } + pub type Ty = ::std::os::raw::c_longlong; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar { + pub baz: root::foo::bar::Ty, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::baz"][::std::mem::offset_of!(Bar, baz) - 0usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace_macro.rs b/bindgen-tests/tests/expectations/tests/inline_namespace_macro.rs new file mode 100644 index 0000000000..99ca607d2f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace_macro.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod repro { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct duration { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of duration"][::std::mem::size_of::() - 1usize]; + ["Alignment of duration"][::std::mem::align_of::() - 1usize]; + }; + } +} diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace_nested.rs b/bindgen-tests/tests/expectations/tests/inline_namespace_nested.rs new file mode 100644 index 0000000000..1474f47ba2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace_nested.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod ranges { + #[allow(unused_imports)] + use self::super::super::root; + pub mod bar { + #[allow(unused_imports)] + use self::super::super::super::root; + pub const bar: ::std::os::raw::c_int = 0; + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/inline_namespace_no_ns_enabled.rs b/bindgen-tests/tests/expectations/tests/inline_namespace_no_ns_enabled.rs new file mode 100644 index 0000000000..66359bd51b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inline_namespace_no_ns_enabled.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug)] +pub struct std_basic_string { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub hider: std_basic_string_Alloc_hider, + pub length: ::std::os::raw::c_ulong, + pub __bindgen_anon_1: std_basic_string__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct std_basic_string_Alloc_hider { + pub storage: *mut ::std::os::raw::c_void, +} +impl Default for std_basic_string_Alloc_hider { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug)] +pub struct std_basic_string__bindgen_ty_1 { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub inline_storage: [CharT; 4usize], +} +impl Default for std_basic_string__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for std_basic_string { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/inner-typedef-gh422.rs b/bindgen-tests/tests/expectations/tests/inner-typedef-gh422.rs new file mode 100644 index 0000000000..16b1eb48ea --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inner-typedef-gh422.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo_InnerType { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +impl Default for Foo_InnerType { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type Bar = InnerType; +unsafe extern "C" { + #[link_name = "\u{1}_Z4funcv"] + pub fn func() -> Bar; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct InnerType { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/inner_const.rs b/bindgen-tests/tests/expectations/tests/inner_const.rs new file mode 100644 index 0000000000..ad8af7ce35 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inner_const.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub bar: ::std::os::raw::c_int, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo3BOOE"] + pub static mut Foo_BOO: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo8whateverE"] + pub static mut Foo_whatever: Foo; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/inner_template_self.rs b/bindgen-tests/tests/expectations/tests/inner_template_self.rs new file mode 100644 index 0000000000..c8f9799be6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/inner_template_self.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct LinkedList { + pub next: *mut LinkedList, + pub prev: *mut LinkedList, +} +impl Default for LinkedList { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct InstantiateIt { + pub m_list: LinkedList, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of InstantiateIt"][::std::mem::size_of::() - 16usize]; + ["Alignment of InstantiateIt"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: InstantiateIt::m_list", + ][::std::mem::offset_of!(InstantiateIt, m_list) - 0usize]; +}; +impl Default for InstantiateIt { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: LinkedList_open0_int_close0", + ][::std::mem::size_of::() - 16usize]; + [ + "Align of template specialization: LinkedList_open0_int_close0", + ][::std::mem::align_of::() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/int128_t.rs b/bindgen-tests/tests/expectations/tests/int128_t.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/int128_t.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/tests/expectations/tests/issue-1025-unknown-enum-repr.rs b/bindgen-tests/tests/expectations/tests/issue-1025-unknown-enum-repr.rs similarity index 80% rename from tests/expectations/tests/issue-1025-unknown-enum-repr.rs rename to bindgen-tests/tests/expectations/tests/issue-1025-unknown-enum-repr.rs index 265109106a..6e27b94ca9 100644 --- a/tests/expectations/tests/issue-1025-unknown-enum-repr.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1025-unknown-enum-repr.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct a { diff --git a/bindgen-tests/tests/expectations/tests/issue-1034.rs b/bindgen-tests/tests/expectations/tests/issue-1034.rs new file mode 100644 index 0000000000..90cc768a94 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1034.rs @@ -0,0 +1,164 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct S2 { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S2"][::std::mem::size_of::() - 2usize]; + ["Alignment of S2"][::std::mem::align_of::() - 1usize]; +}; +impl S2 { + #[inline] + pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + } +} diff --git a/tests/expectations/tests/issue-1040.rs b/bindgen-tests/tests/expectations/tests/issue-1040.rs similarity index 75% rename from tests/expectations/tests/issue-1040.rs rename to bindgen-tests/tests/expectations/tests/issue-1040.rs index 3271d0e812..788c480424 100644 --- a/tests/expectations/tests/issue-1040.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1040.rs @@ -1,7 +1,2 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - pub const g_107: ::std::os::raw::c_ulonglong = 18446744073709551615; diff --git a/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs new file mode 100644 index 0000000000..50e9283b5a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs @@ -0,0 +1,164 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct S1 { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S1"][::std::mem::size_of::() - 3usize]; + ["Alignment of S1"][::std::mem::align_of::() - 1usize]; +}; +impl S1 { + #[inline] + pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1113-template-references.rs b/bindgen-tests/tests/expectations/tests/issue-1113-template-references.rs new file mode 100644 index 0000000000..c0e76d8047 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1113-template-references.rs @@ -0,0 +1,41 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Entry { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: K, + pub mData: V, +} +impl Default for Entry { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct nsBaseHashtable { + pub _address: u8, +} +pub type nsBaseHashtable_EntryType = Entry; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsBaseHashtable_EntryPtr { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub mEntry: *mut nsBaseHashtable_EntryType, + pub mExistingEntry: bool, +} +impl Default for nsBaseHashtable_EntryPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1118-using-forward-decl.rs b/bindgen-tests/tests/expectations/tests/issue-1118-using-forward-decl.rs new file mode 100644 index 0000000000..7df1cdb741 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1118-using-forward-decl.rs @@ -0,0 +1,82 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type c = nsTArray; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray_base { + pub d: *mut ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsTArray_base"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsTArray_base"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: nsTArray_base::d", + ][::std::mem::offset_of!(nsTArray_base, d) - 0usize]; +}; +impl Default for nsTArray_base { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray { + pub _base: nsTArray_base, +} +impl Default for nsTArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsIContent { + pub foo: nsTArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsIContent"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsIContent"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: nsIContent::foo", + ][::std::mem::offset_of!(nsIContent, foo) - 0usize]; +}; +impl Default for nsIContent { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z35Gecko_GetAnonymousContentForElementv"] + pub fn Gecko_GetAnonymousContentForElement() -> *mut nsTArray; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: nsTArray_open0_ptr_nsIContent_close0", + ][::std::mem::size_of::() - 8usize]; + [ + "Align of template specialization: nsTArray_open0_ptr_nsIContent_close0", + ][::std::mem::align_of::() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: nsTArray_open0_ptr_nsIContent_close0", + ][::std::mem::size_of::() - 8usize]; + [ + "Align of template specialization: nsTArray_open0_ptr_nsIContent_close0", + ][::std::mem::align_of::() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs b/bindgen-tests/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs new file mode 100644 index 0000000000..10c769c38c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct Foo__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug)] +pub struct Foo { + pub vtable_: *const Foo__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs similarity index 84% rename from tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs rename to bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs index 8c70625e37..5aaff691b4 100644 --- a/tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-bitfield-enum.rs @@ -1,14 +1,7 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - impl MyDupeEnum { pub const A: MyDupeEnum = MyDupeEnum(0); -} -impl MyDupeEnum { pub const A_alias: MyDupeEnum = MyDupeEnum(0); -} -impl MyDupeEnum { pub const B: MyDupeEnum = MyDupeEnum(1); } impl ::std::ops::BitOr for MyDupeEnum { @@ -37,16 +30,12 @@ impl ::std::ops::BitAndAssign for MyDupeEnum { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct MyDupeEnum(pub u32); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct MyDupeEnum(pub ::std::os::raw::c_uint); impl MyOtherDupeEnum { pub const C: MyOtherDupeEnum = MyOtherDupeEnum(0); -} -impl MyOtherDupeEnum { pub const C_alias: MyOtherDupeEnum = MyOtherDupeEnum(0); -} -impl MyOtherDupeEnum { pub const D: MyOtherDupeEnum = MyOtherDupeEnum(1); } impl ::std::ops::BitOr for MyOtherDupeEnum { @@ -75,6 +64,6 @@ impl ::std::ops::BitAndAssign for MyOtherDupeEnum { self.0 &= rhs.0; } } -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct MyOtherDupeEnum(pub u32); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct MyOtherDupeEnum(pub ::std::os::raw::c_uint); diff --git a/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs new file mode 100644 index 0000000000..a69d005623 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod MyDupeEnum { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const A: Type = 0; + pub const A_alias: Type = 0; + pub const B: Type = 1; +} +pub mod MyOtherDupeEnum { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const C: Type = 0; + pub const C_alias: Type = 0; + pub const D: Type = 1; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs new file mode 100644 index 0000000000..a69d005623 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod MyDupeEnum { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const A: Type = 0; + pub const A_alias: Type = 0; + pub const B: Type = 1; +} +pub mod MyOtherDupeEnum { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const C: Type = 0; + pub const C_alias: Type = 0; + pub const D: Type = 1; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-enum.rs b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-enum.rs new file mode 100644 index 0000000000..f41d6e90ec --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1198-alias-rust-enum.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl MyDupeEnum { + pub const A_alias: MyDupeEnum = MyDupeEnum::A; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MyDupeEnum { + A = 0, + B = 1, +} +impl MyOtherDupeEnum { + pub const C_alias: MyOtherDupeEnum = MyOtherDupeEnum::C; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum MyOtherDupeEnum { + C = 0, + D = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1216-variadic-member.rs b/bindgen-tests/tests/expectations/tests/issue-1216-variadic-member.rs new file mode 100644 index 0000000000..7c562437e4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1216-variadic-member.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn f(a: ::std::os::raw::c_int, ...); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub f: ::std::option::Option< + unsafe extern "C" fn( + p: *mut ::std::os::raw::c_void, + obj: *mut ::std::os::raw::c_void, + a: ::std::os::raw::c_int, + ... + ), + >, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Foo::f"][::std::mem::offset_of!(Foo, f) - 0usize]; +}; diff --git a/tests/expectations/tests/issue-1238-fwd-no-copy.rs b/bindgen-tests/tests/expectations/tests/issue-1238-fwd-no-copy.rs similarity index 79% rename from tests/expectations/tests/issue-1238-fwd-no-copy.rs rename to bindgen-tests/tests/expectations/tests/issue-1238-fwd-no-copy.rs index f2156dfb5a..81e8fed5f3 100644 --- a/tests/expectations/tests/issue-1238-fwd-no-copy.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1238-fwd-no-copy.rs @@ -1,7 +1,4 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - #[repr(C)] #[derive(Debug)] pub struct MyType { diff --git a/bindgen-tests/tests/expectations/tests/issue-1281.rs b/bindgen-tests/tests/expectations/tests/issue-1281.rs new file mode 100644 index 0000000000..03c80d21fb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1281.rs @@ -0,0 +1,35 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar { + pub u: foo, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub foo: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::foo"][::std::mem::offset_of!(foo, foo) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar::u"][::std::mem::offset_of!(bar, u) - 0usize]; +}; +pub type bar_t = bar; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct baz { + pub f: foo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of baz"][::std::mem::align_of::() - 4usize]; + ["Offset of field: baz::f"][::std::mem::offset_of!(baz, f) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-1285.rs b/bindgen-tests/tests/expectations/tests/issue-1285.rs new file mode 100644 index 0000000000..6520163259 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1285.rs @@ -0,0 +1,49 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1291.rs b/bindgen-tests/tests/expectations/tests/issue-1291.rs new file mode 100644 index 0000000000..3c3fab3704 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1291.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct RTCRay { + pub org: [f32; 3usize], + pub align0: f32, + pub dir: [f32; 3usize], + pub align1: f32, + pub tnear: f32, + pub tfar: f32, + pub time: f32, + pub mask: ::std::os::raw::c_uint, + pub Ng: [f32; 3usize], + pub align2: f32, + pub u: f32, + pub v: f32, + pub geomID: ::std::os::raw::c_uint, + pub primID: ::std::os::raw::c_uint, + pub instID: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of RTCRay"][::std::mem::size_of::() - 96usize]; + ["Alignment of RTCRay"][::std::mem::align_of::() - 16usize]; + ["Offset of field: RTCRay::org"][::std::mem::offset_of!(RTCRay, org) - 0usize]; + [ + "Offset of field: RTCRay::align0", + ][::std::mem::offset_of!(RTCRay, align0) - 12usize]; + ["Offset of field: RTCRay::dir"][::std::mem::offset_of!(RTCRay, dir) - 16usize]; + [ + "Offset of field: RTCRay::align1", + ][::std::mem::offset_of!(RTCRay, align1) - 28usize]; + ["Offset of field: RTCRay::tnear"][::std::mem::offset_of!(RTCRay, tnear) - 32usize]; + ["Offset of field: RTCRay::tfar"][::std::mem::offset_of!(RTCRay, tfar) - 36usize]; + ["Offset of field: RTCRay::time"][::std::mem::offset_of!(RTCRay, time) - 40usize]; + ["Offset of field: RTCRay::mask"][::std::mem::offset_of!(RTCRay, mask) - 44usize]; + ["Offset of field: RTCRay::Ng"][::std::mem::offset_of!(RTCRay, Ng) - 48usize]; + [ + "Offset of field: RTCRay::align2", + ][::std::mem::offset_of!(RTCRay, align2) - 60usize]; + ["Offset of field: RTCRay::u"][::std::mem::offset_of!(RTCRay, u) - 64usize]; + ["Offset of field: RTCRay::v"][::std::mem::offset_of!(RTCRay, v) - 68usize]; + [ + "Offset of field: RTCRay::geomID", + ][::std::mem::offset_of!(RTCRay, geomID) - 72usize]; + [ + "Offset of field: RTCRay::primID", + ][::std::mem::offset_of!(RTCRay, primID) - 76usize]; + [ + "Offset of field: RTCRay::instID", + ][::std::mem::offset_of!(RTCRay, instID) - 80usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-1350-attribute-overloadable.rs b/bindgen-tests/tests/expectations/tests/issue-1350-attribute-overloadable.rs new file mode 100644 index 0000000000..c033570793 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1350-attribute-overloadable.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z11my_functioni"] + pub fn my_function(a: ::std::os::raw::c_int); +} +unsafe extern "C" { + #[link_name = "\u{1}_Z11my_functionPKc"] + pub fn my_function1(a: *const ::std::os::raw::c_char); +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1375-prefixed-functions.rs b/bindgen-tests/tests/expectations/tests/issue-1375-prefixed-functions.rs new file mode 100644 index 0000000000..f5e231ea96 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1375-prefixed-functions.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}my_custom_prefix_var_const_name"] + pub static var_const_name: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}my_custom_prefix_var_mut_name"] + pub static mut var_mut_name: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}my_custom_prefix_function_name"] + pub fn function_name(x: ::std::os::raw::c_int); +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1382-rust-primitive-types.rs b/bindgen-tests/tests/expectations/tests/issue-1382-rust-primitive-types.rs new file mode 100644 index 0000000000..277978d93c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1382-rust-primitive-types.rs @@ -0,0 +1,46 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type i8_ = i8; +pub type u8_ = u8; +pub type i16_ = i16; +pub type u16_ = u16; +pub type i32_ = i32; +pub type u32_ = u32; +pub type i64_ = i64; +pub type u64_ = u64; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub i8_: ::std::os::raw::c_int, + pub u8_: ::std::os::raw::c_int, + pub i16_: ::std::os::raw::c_int, + pub u16_: ::std::os::raw::c_int, + pub i32_: ::std::os::raw::c_int, + pub u32_: ::std::os::raw::c_int, + pub i64_: ::std::os::raw::c_int, + pub u64_: ::std::os::raw::c_int, + pub i128_: ::std::os::raw::c_int, + pub u128_: ::std::os::raw::c_int, + pub isize_: ::std::os::raw::c_int, + pub usize_: ::std::os::raw::c_int, + pub f32_: ::std::os::raw::c_int, + pub f64_: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 56usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::i8_"][::std::mem::offset_of!(Foo, i8_) - 0usize]; + ["Offset of field: Foo::u8_"][::std::mem::offset_of!(Foo, u8_) - 4usize]; + ["Offset of field: Foo::i16_"][::std::mem::offset_of!(Foo, i16_) - 8usize]; + ["Offset of field: Foo::u16_"][::std::mem::offset_of!(Foo, u16_) - 12usize]; + ["Offset of field: Foo::i32_"][::std::mem::offset_of!(Foo, i32_) - 16usize]; + ["Offset of field: Foo::u32_"][::std::mem::offset_of!(Foo, u32_) - 20usize]; + ["Offset of field: Foo::i64_"][::std::mem::offset_of!(Foo, i64_) - 24usize]; + ["Offset of field: Foo::u64_"][::std::mem::offset_of!(Foo, u64_) - 28usize]; + ["Offset of field: Foo::i128_"][::std::mem::offset_of!(Foo, i128_) - 32usize]; + ["Offset of field: Foo::u128_"][::std::mem::offset_of!(Foo, u128_) - 36usize]; + ["Offset of field: Foo::isize_"][::std::mem::offset_of!(Foo, isize_) - 40usize]; + ["Offset of field: Foo::usize_"][::std::mem::offset_of!(Foo, usize_) - 44usize]; + ["Offset of field: Foo::f32_"][::std::mem::offset_of!(Foo, f32_) - 48usize]; + ["Offset of field: Foo::f64_"][::std::mem::offset_of!(Foo, f64_) - 52usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-1435.rs b/bindgen-tests/tests/expectations/tests/issue-1435.rs new file mode 100644 index 0000000000..b50e1f88c0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1435.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod ns { + #[allow(unused_imports)] + use self::super::super::root; + pub const AB_A: AB = 0; + pub const AB_B: AB = 1; + pub type AB = ::std::os::raw::c_int; + } + pub use self::super::root::ns::AB as AB; + unsafe extern "C" { + #[link_name = "\u{1}_ZL2kA"] + pub static kA: root::AB; + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1443.rs b/bindgen-tests/tests/expectations/tests/issue-1443.rs new file mode 100644 index 0000000000..ee1ffca8e5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1443.rs @@ -0,0 +1,94 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub f: *const Foo, + pub m: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 16usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::f"][::std::mem::offset_of!(Bar, f) - 0usize]; + ["Offset of field: Bar::m"][::std::mem::offset_of!(Bar, m) - 8usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Baz { + pub f: *mut Foo, + pub m: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 16usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Baz::f"][::std::mem::offset_of!(Baz, f) - 0usize]; + ["Offset of field: Baz::m"][::std::mem::offset_of!(Baz, m) - 8usize]; +}; +impl Default for Baz { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Tar { + pub f: *const Foo, + pub m: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Tar"][::std::mem::size_of::() - 16usize]; + ["Alignment of Tar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Tar::f"][::std::mem::offset_of!(Tar, f) - 0usize]; + ["Offset of field: Tar::m"][::std::mem::offset_of!(Tar, m) - 8usize]; +}; +impl Default for Tar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Taz { + pub f: *mut Foo, + pub m: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Taz"][::std::mem::size_of::() - 16usize]; + ["Alignment of Taz"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Taz::f"][::std::mem::offset_of!(Taz, f) - 0usize]; + ["Offset of field: Taz::m"][::std::mem::offset_of!(Taz, m) - 8usize]; +}; +impl Default for Taz { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1454.rs b/bindgen-tests/tests/expectations/tests/issue-1454.rs new file mode 100644 index 0000000000..325ccfd977 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1454.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug)] +pub struct extern_type; +#[repr(C)] +#[derive(Debug)] +pub struct local_type { + pub inner: extern_type, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of local_type"][::std::mem::size_of::() - 0usize]; + ["Alignment of local_type"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: local_type::inner", + ][::std::mem::offset_of!(local_type, inner) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-1464.rs b/bindgen-tests/tests/expectations/tests/issue-1464.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1464.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/issue-1488-enum-new-type.rs b/bindgen-tests/tests/expectations/tests/issue-1488-enum-new-type.rs new file mode 100644 index 0000000000..ab4b6fc971 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1488-enum-new-type.rs @@ -0,0 +1,45 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const Foo_A: Foo = 0; +pub const Foo_B: Foo = 1; +pub type Foo = ::std::os::raw::c_uint; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct FooAlias(pub Foo); +pub mod Bar { + #[allow(unused_imports)] + use super::*; + pub type Type = ::std::os::raw::c_uint; + pub const C: Type = 0; + pub const D: Type = 1; +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct BarAlias(pub Bar::Type); +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Qux { + E = 0, + F = 1, +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct QuxAlias(pub Qux); +pub const Baz_G: Baz = 0; +pub const Baz_H: Baz = 1; +pub type Baz = ::std::os::raw::c_uint; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct BazAlias(pub Baz); +impl ::std::ops::Deref for BazAlias { + type Target = Baz; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl ::std::ops::DerefMut for BazAlias { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1488-options.rs b/bindgen-tests/tests/expectations/tests/issue-1488-options.rs new file mode 100644 index 0000000000..0f6efb93d4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1488-options.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type OSStatus = ::std::os::raw::c_int; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct SomePtr(pub *mut ::std::os::raw::c_void); +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct AnotherPtr(pub *mut ::std::os::raw::c_void); +impl ::std::ops::Deref for AnotherPtr { + type Target = *mut ::std::os::raw::c_void; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl ::std::ops::DerefMut for AnotherPtr { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1488-template-alias-new-type.rs b/bindgen-tests/tests/expectations/tests/issue-1488-template-alias-new-type.rs new file mode 100644 index 0000000000..de43753e9c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1488-template-alias-new-type.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Wrapped(pub T); diff --git a/bindgen-tests/tests/expectations/tests/issue-1498.rs b/bindgen-tests/tests/expectations/tests/issue-1498.rs new file mode 100644 index 0000000000..286d2eb6ee --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1498.rs @@ -0,0 +1,82 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C, packed)] +#[derive(Copy, Clone)] +pub struct rte_memseg { + ///< Start physical address. + pub phys_addr: u64, + pub __bindgen_anon_1: rte_memseg__bindgen_ty_1, + ///< Length of the segment. + pub len: usize, + ///< The pagesize of underlying memory + pub hugepage_sz: u64, + ///< NUMA socket ID. + pub socket_id: i32, + ///< Number of channels. + pub nchannel: u32, + ///< Number of ranks. + pub nrank: u32, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_memseg__bindgen_ty_1 { + ///< Start virtual address. + pub addr: *mut ::std::os::raw::c_void, + ///< Makes sure addr is always 64 bits + pub addr_64: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_memseg__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_memseg__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_memseg__bindgen_ty_1::addr", + ][::std::mem::offset_of!(rte_memseg__bindgen_ty_1, addr) - 0usize]; + [ + "Offset of field: rte_memseg__bindgen_ty_1::addr_64", + ][::std::mem::offset_of!(rte_memseg__bindgen_ty_1, addr_64) - 0usize]; +}; +impl Default for rte_memseg__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_memseg"][::std::mem::size_of::() - 44usize]; + ["Alignment of rte_memseg"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: rte_memseg::phys_addr", + ][::std::mem::offset_of!(rte_memseg, phys_addr) - 0usize]; + [ + "Offset of field: rte_memseg::len", + ][::std::mem::offset_of!(rte_memseg, len) - 16usize]; + [ + "Offset of field: rte_memseg::hugepage_sz", + ][::std::mem::offset_of!(rte_memseg, hugepage_sz) - 24usize]; + [ + "Offset of field: rte_memseg::socket_id", + ][::std::mem::offset_of!(rte_memseg, socket_id) - 32usize]; + [ + "Offset of field: rte_memseg::nchannel", + ][::std::mem::offset_of!(rte_memseg, nchannel) - 36usize]; + [ + "Offset of field: rte_memseg::nrank", + ][::std::mem::offset_of!(rte_memseg, nrank) - 40usize]; +}; +impl Default for rte_memseg { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1514.rs b/bindgen-tests/tests/expectations/tests/issue-1514.rs new file mode 100644 index 0000000000..aef63037ae --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1514.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Thing { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Thing_Inner { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: *mut T, +} +impl Default for Thing_Inner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Thing_AnotherInner { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: Thing_Inner, +} +impl Default for Thing_AnotherInner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1554.rs b/bindgen-tests/tests/expectations/tests/issue-1554.rs new file mode 100644 index 0000000000..7b1a2cd410 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1554.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#![feature(non_exhaustive)] +#[repr(u32)] +#[non_exhaustive] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Planet { + earth = 0, + mars = 1, +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1599-opaque-typedef-to-enum.rs b/bindgen-tests/tests/expectations/tests/issue-1599-opaque-typedef-to-enum.rs new file mode 100644 index 0000000000..325ee4adc4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1599-opaque-typedef-to-enum.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const a_b: a = 0; +pub const a_c: a = 1; +pub type a = ::std::os::raw::c_uint; +pub type d = u32; diff --git a/bindgen-tests/tests/expectations/tests/issue-1676-macro-namespace-prefix.rs b/bindgen-tests/tests/expectations/tests/issue-1676-macro-namespace-prefix.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1676-macro-namespace-prefix.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/issue-1947.rs b/bindgen-tests/tests/expectations/tests/issue-1947.rs new file mode 100644 index 0000000000..795b033a12 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1947.rs @@ -0,0 +1,641 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +pub type U8 = ::std::os::raw::c_uchar; +pub type U16 = ::std::os::raw::c_ushort; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct V56AMDY { + pub _bindgen_align: [u16; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub MADK: U8, + pub MABR: U8, + pub _bitfield_2: __BindgenBitfieldUnit<[u8; 3usize]>, + pub _rB_: U8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of V56AMDY"][::std::mem::size_of::() - 8usize]; + ["Alignment of V56AMDY"][::std::mem::align_of::() - 2usize]; + ["Offset of field: V56AMDY::MADK"][::std::mem::offset_of!(V56AMDY, MADK) - 2usize]; + ["Offset of field: V56AMDY::MABR"][::std::mem::offset_of!(V56AMDY, MABR) - 3usize]; + ["Offset of field: V56AMDY::_rB_"][::std::mem::offset_of!(V56AMDY, _rB_) - 7usize]; +}; +impl V56AMDY { + #[inline] + pub fn MADZ(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 10u8) as u16) } + } + #[inline] + pub fn set_MADZ(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 10u8, val as u64) + } + } + #[inline] + pub unsafe fn MADZ_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 10u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MADZ_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 10u8, + val as u64, + ) + } + } + #[inline] + pub fn MAI0(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 2u8) as u16) } + } + #[inline] + pub fn set_MAI0(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(10usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn MAI0_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 10usize, 2u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MAI0_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 10usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn MAI1(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 2u8) as u16) } + } + #[inline] + pub fn set_MAI1(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn MAI1_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 12usize, 2u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MAI1_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 12usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn MAI2(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 2u8) as u16) } + } + #[inline] + pub fn set_MAI2(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(14usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn MAI2_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 14usize, 2u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MAI2_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 14usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + MADZ: U16, + MAI0: U16, + MAI1: U16, + MAI2: U16, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 10u8, + { + let MADZ: u16 = unsafe { ::std::mem::transmute(MADZ) }; + MADZ as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 10usize, + 2u8, + { + let MAI0: u16 = unsafe { ::std::mem::transmute(MAI0) }; + MAI0 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 12usize, + 2u8, + { + let MAI1: u16 = unsafe { ::std::mem::transmute(MAI1) }; + MAI1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 2u8, + { + let MAI2: u16 = unsafe { ::std::mem::transmute(MAI2) }; + MAI2 as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub fn MATH(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 10u8) as u16) } + } + #[inline] + pub fn set_MATH(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_2.set(0usize, 10u8, val as u64) + } + } + #[inline] + pub unsafe fn MATH_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 0usize, 10u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MATH_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 0usize, + 10u8, + val as u64, + ) + } + } + #[inline] + pub fn MATE(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(10usize, 4u8) as u16) } + } + #[inline] + pub fn set_MATE(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_2.set(10usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn MATE_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 10usize, 4u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MATE_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 10usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn MATW(&self) -> U16 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(14usize, 2u8) as u16) } + } + #[inline] + pub fn set_MATW(&mut self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_2.set(14usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn MATW_raw(this: *const Self) -> U16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 14usize, 2u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_MATW_raw(this: *mut Self, val: U16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 14usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn MASW(&self) -> U8 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(16usize, 4u8) as u8) } + } + #[inline] + pub fn set_MASW(&mut self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(16usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn MASW_raw(this: *const Self) -> U8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 16usize, 4u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_MASW_raw(this: *mut Self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 16usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn MABW(&self) -> U8 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(20usize, 3u8) as u8) } + } + #[inline] + pub fn set_MABW(&mut self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(20usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn MABW_raw(this: *const Self) -> U8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 20usize, 3u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_MABW_raw(this: *mut Self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 20usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn MAXN(&self) -> U8 { + unsafe { ::std::mem::transmute(self._bitfield_2.get(23usize, 1u8) as u8) } + } + #[inline] + pub fn set_MAXN(&mut self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(23usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn MAXN_raw(this: *const Self) -> U8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 23usize, 1u8) + as u8, + ) + } + } + #[inline] + pub unsafe fn set_MAXN_raw(this: *mut Self, val: U8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 23usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_2( + MATH: U16, + MATE: U16, + MATW: U16, + MASW: U8, + MABW: U8, + MAXN: U8, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 10u8, + { + let MATH: u16 = unsafe { ::std::mem::transmute(MATH) }; + MATH as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 10usize, + 4u8, + { + let MATE: u16 = unsafe { ::std::mem::transmute(MATE) }; + MATE as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 2u8, + { + let MATW: u16 = unsafe { ::std::mem::transmute(MATW) }; + MATW as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 4u8, + { + let MASW: u8 = unsafe { ::std::mem::transmute(MASW) }; + MASW as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 20usize, + 3u8, + { + let MABW: u8 = unsafe { ::std::mem::transmute(MABW) }; + MABW as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 23usize, + 1u8, + { + let MAXN: u8 = unsafe { ::std::mem::transmute(MAXN) }; + MAXN as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1977-larger-arrays.rs b/bindgen-tests/tests/expectations/tests/issue-1977-larger-arrays.rs new file mode 100644 index 0000000000..df7a2192ed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1977-larger-arrays.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct S { + pub large_array: [::std::os::raw::c_char; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S"][::std::mem::size_of::() - 33usize]; + ["Alignment of S"][::std::mem::align_of::() - 1usize]; + ["Offset of field: S::large_array"][::std::mem::offset_of!(S, large_array) - 0usize]; +}; +impl Default for S { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ST { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub large_array: [T; 33usize], +} +impl Default for ST { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-1995.rs b/bindgen-tests/tests/expectations/tests/issue-1995.rs new file mode 100644 index 0000000000..0e36bdd9c9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-1995.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** This is a constant that has a docstring + + And expected to be found in generated bindings code too.*/ +pub const FOO: ::std::os::raw::c_int = 1; +/** This is a constant that has a docstring + + And expected to be found in generated bindings code too.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub baz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::baz"][::std::mem::offset_of!(Bar, baz) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-2019.rs b/bindgen-tests/tests/expectations/tests/issue-2019.rs new file mode 100644 index 0000000000..4c91cf9972 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2019.rs @@ -0,0 +1,43 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub a: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 4usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::a"][::std::mem::offset_of!(A, a) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1A4makeEv"] + pub fn make() -> A; +} +impl A { + #[inline] + pub unsafe fn make() -> A { + make() + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct B { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 4usize]; + ["Alignment of B"][::std::mem::align_of::() - 4usize]; + ["Offset of field: B::b"][::std::mem::offset_of!(B, b) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1B4makeEv"] + pub fn make1() -> B; +} +impl B { + #[inline] + pub unsafe fn make() -> B { + make1() + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-2239-template-dependent-bit-width.rs b/bindgen-tests/tests/expectations/tests/issue-2239-template-dependent-bit-width.rs new file mode 100644 index 0000000000..6ff58b7559 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2239-template-dependent-bit-width.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct b { + pub _address: u8, +} +pub type b_td = a; +pub type b_ta = a; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct b_foo { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/issue-2556.rs b/bindgen-tests/tests/expectations/tests/issue-2556.rs new file mode 100644 index 0000000000..92fe5026b8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2556.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct nsSize { + pub width: ::std::os::raw::c_int, + pub height: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of nsSize"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsSize"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: nsSize::width", + ][::std::mem::offset_of!(nsSize, width) - 0usize]; + [ + "Offset of field: nsSize::height", + ][::std::mem::offset_of!(nsSize, height) - 4usize]; + }; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN3fooL22kFallbackIntrinsicSizeE"] + pub static kFallbackIntrinsicSize: root::nsSize; + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-2566-cstr.rs b/bindgen-tests/tests/expectations/tests/issue-2566-cstr.rs new file mode 100644 index 0000000000..4227cf2956 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2566-cstr.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FOO: &[u8; 4] = b"a\0b\0"; diff --git a/bindgen-tests/tests/expectations/tests/issue-2566.rs b/bindgen-tests/tests/expectations/tests/issue-2566.rs new file mode 100644 index 0000000000..4227cf2956 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2566.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FOO: &[u8; 4] = b"a\0b\0"; diff --git a/bindgen-tests/tests/expectations/tests/issue-2618.rs b/bindgen-tests/tests/expectations/tests/issue-2618.rs new file mode 100644 index 0000000000..ecac1ec81e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2618.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const val1: u32 = 2147483647; +pub const val2: u32 = 2147483648; +pub const val3: u32 = 4294967295; +pub const val4: u64 = 9223372036854775807; +pub const val5: u64 = 9223372036854775808; +pub const val6: u64 = 18446744073709551615; +pub const val7: u32 = 2147483647; +pub const val8: u32 = 2147483648; +pub const val9: u32 = 4294967295; +pub const val10: u64 = 9223372036854775807; +pub const val11: u64 = 9223372036854775808; +pub const val12: u64 = 18446744073709551615; diff --git a/bindgen-tests/tests/expectations/tests/issue-2695.rs b/bindgen-tests/tests/expectations/tests/issue-2695.rs new file mode 100644 index 0000000000..20a016dbab --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2695.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test { + pub x: ::std::os::raw::c_ulong, + pub a: ::std::os::raw::c_char, + pub b: ::std::os::raw::c_char, + pub c: ::std::os::raw::c_char, + pub __bindgen_padding_0: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 12usize]; + ["Alignment of Test"][::std::mem::align_of::() - 2usize]; + ["Offset of field: Test::x"][::std::mem::offset_of!(Test, x) - 0usize]; + ["Offset of field: Test::a"][::std::mem::offset_of!(Test, a) - 8usize]; + ["Offset of field: Test::b"][::std::mem::offset_of!(Test, b) - 9usize]; + ["Offset of field: Test::c"][::std::mem::offset_of!(Test, c) - 10usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-2966.rs b/bindgen-tests/tests/expectations/tests/issue-2966.rs new file mode 100644 index 0000000000..bfdcbd9e2f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2966.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct pub_var1(pub *const ::std::os::raw::c_char); +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct pubcrate_var2(pub(crate) *const ::std::os::raw::c_char); +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct private_var3(*const ::std::os::raw::c_char); diff --git a/bindgen-tests/tests/expectations/tests/issue-3027.rs b/bindgen-tests/tests/expectations/tests/issue-3027.rs new file mode 100644 index 0000000000..c8c2a7e542 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-3027.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] + #[repr(C)] + pub struct __BindgenOpaqueArray(pub T); + impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } + } + #[allow(unused_imports)] + use self::super::root; + pub mod regression { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct C { + pub a: root::__BindgenOpaqueArray<[u8; 3usize]>, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of C"][::std::mem::size_of::() - 3usize]; + ["Alignment of C"][::std::mem::align_of::() - 1usize]; + ["Offset of field: C::a"][::std::mem::offset_of!(C, a) - 0usize]; + }; + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-358.rs b/bindgen-tests/tests/expectations/tests/issue-358.rs new file mode 100644 index 0000000000..ff915e9fba --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-358.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct JS_PersistentRooted { + pub _base: a, +} +impl Default for JS_PersistentRooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct a { + pub b: *mut a, +} +impl Default for a { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-372.rs b/bindgen-tests/tests/expectations/tests/issue-372.rs new file mode 100644 index 0000000000..cf00a70743 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-372.rs @@ -0,0 +1,85 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] + #[repr(C, align(8))] + pub struct __BindgenOpaqueArray8(pub T); + impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } + } + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct i { + pub j: *mut root::i, + pub k: *mut root::i, + pub l: bool, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of i"][::std::mem::size_of::() - 24usize]; + ["Alignment of i"][::std::mem::align_of::() - 8usize]; + ["Offset of field: i::j"][::std::mem::offset_of!(i, j) - 0usize]; + ["Offset of field: i::k"][::std::mem::offset_of!(i, k) - 8usize]; + ["Offset of field: i::l"][::std::mem::offset_of!(i, l) - 16usize]; + }; + impl Default for i { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct d { + pub m: root::i, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of d"][::std::mem::size_of::() - 24usize]; + ["Alignment of d"][::std::mem::align_of::() - 8usize]; + ["Offset of field: d::m"][::std::mem::offset_of!(d, m) - 0usize]; + }; + impl Default for d { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum n { + o = 0, + p = 1, + q = 2, + r = 3, + s = 4, + t = 5, + b = 6, + ae = 7, + e = 8, + ag = 9, + ah = 10, + ai = 11, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct F { + pub w: root::__BindgenOpaqueArray8<[u8; 264usize]>, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of F"][::std::mem::size_of::() - 264usize]; + ["Alignment of F"][::std::mem::align_of::() - 8usize]; + ["Offset of field: F::w"][::std::mem::offset_of!(F, w) - 0usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-410.rs b/bindgen-tests/tests/expectations/tests/issue-410.rs new file mode 100644 index 0000000000..cda9b6e338 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-410.rs @@ -0,0 +1,35 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod JS { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Value { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Value"][::std::mem::size_of::() - 1usize]; + ["Alignment of Value"][::std::mem::align_of::() - 1usize]; + }; + unsafe extern "C" { + #[link_name = "\u{1}_ZN2JS5Value1aE10JSWhyMagic"] + pub fn Value_a(this: *mut root::JS::Value, arg1: root::JSWhyMagic); + } + impl Value { + #[inline] + pub unsafe fn a(&mut self, arg1: root::JSWhyMagic) { + Value_a(self, arg1) + } + } + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum JSWhyMagic { + __bindgen_cannot_repr_c_on_empty_enum = 0, + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-446.rs b/bindgen-tests/tests/expectations/tests/issue-446.rs new file mode 100644 index 0000000000..5d625cb311 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-446.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct List { + pub next: *mut List, +} +impl Default for List { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PersistentRooted { + pub root_list: List, +} +impl Default for PersistentRooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-447.rs b/bindgen-tests/tests/expectations/tests/issue-447.rs new file mode 100644 index 0000000000..8867a359a2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-447.rs @@ -0,0 +1,57 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod mozilla { + #[allow(unused_imports)] + use self::super::super::root; + pub mod detail { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct GuardObjectNotifier { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of GuardObjectNotifier", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of GuardObjectNotifier", + ][::std::mem::align_of::() - 1usize]; + }; + } + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct JSAutoCompartment { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of JSAutoCompartment", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of JSAutoCompartment", + ][::std::mem::align_of::() - 1usize]; + }; + unsafe extern "C" { + #[link_name = "\u{1}_ZN17JSAutoCompartmentC1EN7mozilla6detail19GuardObjectNotifierE"] + pub fn JSAutoCompartment_JSAutoCompartment( + this: *mut root::JSAutoCompartment, + arg1: root::mozilla::detail::GuardObjectNotifier, + ); + } + impl JSAutoCompartment { + #[inline] + pub unsafe fn new(arg1: root::mozilla::detail::GuardObjectNotifier) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + JSAutoCompartment_JSAutoCompartment(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-493.rs b/bindgen-tests/tests/expectations/tests/issue-493.rs new file mode 100644 index 0000000000..d2e4ea5375 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-493.rs @@ -0,0 +1,168 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct basic_string { + pub _address: u8, +} +pub type basic_string_size_type = ::std::os::raw::c_ulonglong; +pub type basic_string_value_type = ::std::os::raw::c_char; +pub type basic_string_pointer = *mut basic_string_value_type; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct basic_string___long { + pub __cap_: basic_string_size_type, + pub __size_: basic_string_size_type, + pub __data_: basic_string_pointer, +} +impl Default for basic_string___long { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const basic_string___min_cap: basic_string__bindgen_ty_1 = basic_string__bindgen_ty_1::__min_cap; +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum basic_string__bindgen_ty_1 { + __min_cap = 0, +} +#[repr(C)] +pub struct basic_string___short { + pub __bindgen_anon_1: basic_string___short__bindgen_ty_1, + pub __data_: *mut basic_string_value_type, +} +#[repr(C)] +pub union basic_string___short__bindgen_ty_1 { + pub __size_: ::std::os::raw::c_uchar, + pub __lx: basic_string_value_type, +} +impl Default for basic_string___short__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for basic_string___short { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(1))] +pub struct basic_string___ulx { + pub __lx: __BindgenUnionField, + pub __lxx: __BindgenUnionField, + pub bindgen_union_field: [u8; 0usize], +} +impl Default for basic_string___ulx { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const basic_string___n_words: basic_string__bindgen_ty_2 = basic_string__bindgen_ty_2::__n_words; +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum basic_string__bindgen_ty_2 { + __n_words = 0, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct basic_string___raw { + pub __words: *mut basic_string_size_type, +} +impl Default for basic_string___raw { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct basic_string___rep { + pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1, +} +#[repr(C)] +#[repr(align(1))] +pub struct basic_string___rep__bindgen_ty_1 { + pub __l: __BindgenUnionField, + pub __s: __BindgenUnionField, + pub __r: __BindgenUnionField, + pub bindgen_union_field: [u8; 0usize], +} +impl Default for basic_string___rep__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for basic_string___rep { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-511.rs b/bindgen-tests/tests/expectations/tests/issue-511.rs new file mode 100644 index 0000000000..9d26b334c3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-511.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut a: *mut ::std::os::raw::c_char; +} +unsafe extern "C" { + pub static mut b: *const ::std::os::raw::c_char; +} +unsafe extern "C" { + pub static c: *mut ::std::os::raw::c_char; +} +unsafe extern "C" { + pub static d: *const ::std::os::raw::c_char; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-537-repr-packed-n.rs b/bindgen-tests/tests/expectations/tests/issue-537-repr-packed-n.rs new file mode 100644 index 0000000000..881cb9c8ed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-537-repr-packed-n.rs @@ -0,0 +1,61 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +/** This should not be opaque; we can see the attributes and can pack the + struct.*/ +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AlignedToOne { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AlignedToOne"][::std::mem::size_of::() - 4usize]; + ["Alignment of AlignedToOne"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: AlignedToOne::i", + ][::std::mem::offset_of!(AlignedToOne, i) - 0usize]; +}; +/// This should be packed because Rust 1.33 has `#[repr(packed(N))]`. +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct AlignedToTwo { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AlignedToTwo"][::std::mem::size_of::() - 4usize]; + ["Alignment of AlignedToTwo"][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: AlignedToTwo::i", + ][::std::mem::offset_of!(AlignedToTwo, i) - 0usize]; +}; +/** This should not be opaque because although `libclang` doesn't give us the + `#pragma pack(1)`, we can detect that alignment is 1 and add + `#[repr(packed)]` to the struct ourselves.*/ +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PackedToOne { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PackedToOne"][::std::mem::size_of::() - 8usize]; + ["Alignment of PackedToOne"][::std::mem::align_of::() - 1usize]; + ["Offset of field: PackedToOne::x"][::std::mem::offset_of!(PackedToOne, x) - 0usize]; + ["Offset of field: PackedToOne::y"][::std::mem::offset_of!(PackedToOne, y) - 4usize]; +}; +/// This should be packed because Rust 1.33 has `#[repr(packed(N))]`. +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct PackedToTwo { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PackedToTwo"][::std::mem::size_of::() - 8usize]; + ["Alignment of PackedToTwo"][::std::mem::align_of::() - 2usize]; + ["Offset of field: PackedToTwo::x"][::std::mem::offset_of!(PackedToTwo, x) - 0usize]; + ["Offset of field: PackedToTwo::y"][::std::mem::offset_of!(PackedToTwo, y) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-537.rs b/bindgen-tests/tests/expectations/tests/issue-537.rs new file mode 100644 index 0000000000..d630b9ea4c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-537.rs @@ -0,0 +1,63 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** This should not be opaque; we can see the attributes and can pack the + struct.*/ +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AlignedToOne { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AlignedToOne"][::std::mem::size_of::() - 4usize]; + ["Alignment of AlignedToOne"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: AlignedToOne::i", + ][::std::mem::offset_of!(AlignedToOne, i) - 0usize]; +}; +/** This should be opaque because although we can see the attributes, Rust before + 1.33 doesn't have `#[repr(packed(N))]`.*/ +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct AlignedToTwo { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AlignedToTwo"][::std::mem::size_of::() - 4usize]; + ["Alignment of AlignedToTwo"][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: AlignedToTwo::i", + ][::std::mem::offset_of!(AlignedToTwo, i) - 0usize]; +}; +/** This should not be opaque because although `libclang` doesn't give us the + `#pragma pack(1)`, we can detect that alignment is 1 and add + `#[repr(packed)]` to the struct ourselves.*/ +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PackedToOne { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PackedToOne"][::std::mem::size_of::() - 8usize]; + ["Alignment of PackedToOne"][::std::mem::align_of::() - 1usize]; + ["Offset of field: PackedToOne::x"][::std::mem::offset_of!(PackedToOne, x) - 0usize]; + ["Offset of field: PackedToOne::y"][::std::mem::offset_of!(PackedToOne, y) - 4usize]; +}; +/** In this case, even if we can detect the weird alignment triggered by + `#pragma pack(2)`, we can't do anything about it because Rust before 1.33 + doesn't have `#[repr(packed(N))]`. Therefore, we must make it opaque.*/ +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct PackedToTwo { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PackedToTwo"][::std::mem::size_of::() - 8usize]; + ["Alignment of PackedToTwo"][::std::mem::align_of::() - 2usize]; + ["Offset of field: PackedToTwo::x"][::std::mem::offset_of!(PackedToTwo, x) - 0usize]; + ["Offset of field: PackedToTwo::y"][::std::mem::offset_of!(PackedToTwo, y) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce-2.rs b/bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce-2.rs new file mode 100644 index 0000000000..a160d0275d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce-2.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + pub member: *mut Foo_SecondAlias, +} +pub type Foo_FirstAlias = __BindgenOpaqueArray<[u8; 0usize]>; +pub type Foo_SecondAlias = Foo; +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/issue-544-stylo-creduce.rs b/bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce.rs similarity index 77% rename from tests/expectations/tests/issue-544-stylo-creduce.rs rename to bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce.rs index fbee3b2556..b9c42ae12a 100644 --- a/tests/expectations/tests/issue-544-stylo-creduce.rs +++ b/bindgen-tests/tests/expectations/tests/issue-544-stylo-creduce.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct a { diff --git a/bindgen-tests/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs b/bindgen-tests/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs new file mode 100644 index 0000000000..567325b82d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const ENUM_VARIANT_1: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_1; +pub const ENUM_VARIANT_2: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_2; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + ENUM_VARIANT_1 = 0, + ENUM_VARIANT_2 = 1, +} +pub type JS_Alias = u8; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct JS_Base { + pub f: JS_Alias, +} +impl Default for JS_Base { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct JS_AutoIdVector { + pub _base: JS_Base, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of JS_AutoIdVector"][::std::mem::size_of::() - 1usize]; + ["Alignment of JS_AutoIdVector"][::std::mem::align_of::() - 1usize]; +}; +impl Default for JS_AutoIdVector { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: JS_Base_open0_int_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: JS_Base_open0_int_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-573-layout-test-failures.rs b/bindgen-tests/tests/expectations/tests/issue-573-layout-test-failures.rs new file mode 100644 index 0000000000..aa5f457792 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-573-layout-test-failures.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer { + pub i: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct AutoIdVector { + pub ar: Outer, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AutoIdVector"][::std::mem::size_of::() - 1usize]; + ["Alignment of AutoIdVector"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: AutoIdVector::ar", + ][::std::mem::offset_of!(AutoIdVector, ar) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Outer_open0_int_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: Outer_open0_int_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs b/bindgen-tests/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs new file mode 100644 index 0000000000..9968501397 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct a { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct _bindgen_ty_1 { + pub ar: a, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 1usize]; + ["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 1usize]; + [ + "Offset of field: _bindgen_ty_1::ar", + ][::std::mem::offset_of!(_bindgen_ty_1, ar) - 0usize]; +}; +unsafe extern "C" { + pub static mut AutoIdVector: _bindgen_ty_1; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: a_open0_int_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: a_open0_int_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs b/bindgen-tests/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs new file mode 100644 index 0000000000..2a85837e3d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs @@ -0,0 +1,82 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type RefPtr = T; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +pub type A_a = b; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +pub struct e { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub d: RefPtr, +} +impl Default for e { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct f { + pub _address: u8, +} +#[repr(C)] +pub struct g { + pub h: f, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of g"][::std::mem::size_of::() - 1usize]; + ["Alignment of g"][::std::mem::align_of::() - 1usize]; + ["Offset of field: g::h"][::std::mem::offset_of!(g, h) - 0usize]; +}; +impl Default for g { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct b { + pub _base: g, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of b"][::std::mem::size_of::() - 1usize]; + ["Alignment of b"][::std::mem::align_of::() - 1usize]; +}; +impl Default for b { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z25Servo_Element_GetSnapshotv"] + pub fn Servo_Element_GetSnapshot() -> A; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: f_open0_e_open1_int_close1_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: f_open0_e_open1_int_close1_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs b/bindgen-tests/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs new file mode 100644 index 0000000000..db94687737 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RefPtr { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub use_of_t: T, +} +impl Default for RefPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesRefPtrWithAliasedTypeParam { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: RefPtr>, +} +pub type UsesRefPtrWithAliasedTypeParam_V = U; +impl Default for UsesRefPtrWithAliasedTypeParam { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-639-typedef-anon-field.rs b/bindgen-tests/tests/expectations/tests/issue-639-typedef-anon-field.rs new file mode 100644 index 0000000000..e940db1103 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-639-typedef-anon-field.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub bar: Foo_Bar, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo_Bar { + pub abc: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo_Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo_Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo_Bar::abc"][::std::mem::offset_of!(Foo_Bar, abc) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::bar"][::std::mem::offset_of!(Foo, bar) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz_Bar { + pub abc: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz_Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Baz_Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Baz_Bar::abc"][::std::mem::offset_of!(Baz_Bar, abc) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 1usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-643-inner-struct.rs b/bindgen-tests/tests/expectations/tests/issue-643-inner-struct.rs new file mode 100644 index 0000000000..0012c8f6aa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-643-inner-struct.rs @@ -0,0 +1,94 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug)] +pub struct rte_ring { + pub memzone: *mut rte_memzone, + pub prod: rte_ring_prod, + pub cons: rte_ring_cons, + pub ring: __IncompleteArrayField<*mut ::std::os::raw::c_void>, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct rte_ring_prod { + pub watermark: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ring_prod"][::std::mem::size_of::() - 4usize]; + ["Alignment of rte_ring_prod"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ring_prod::watermark", + ][::std::mem::offset_of!(rte_ring_prod, watermark) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct rte_ring_cons { + pub sc_dequeue: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ring_cons"][::std::mem::size_of::() - 4usize]; + ["Alignment of rte_ring_cons"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_ring_cons::sc_dequeue", + ][::std::mem::offset_of!(rte_ring_cons, sc_dequeue) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ring"][::std::mem::size_of::() - 16usize]; + ["Alignment of rte_ring"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_ring::memzone", + ][::std::mem::offset_of!(rte_ring, memzone) - 0usize]; + ["Offset of field: rte_ring::prod"][::std::mem::offset_of!(rte_ring, prod) - 8usize]; + [ + "Offset of field: rte_ring::cons", + ][::std::mem::offset_of!(rte_ring, cons) - 12usize]; + [ + "Offset of field: rte_ring::ring", + ][::std::mem::offset_of!(rte_ring, ring) - 16usize]; +}; +impl Default for rte_ring { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct rte_memzone { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs b/bindgen-tests/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs new file mode 100644 index 0000000000..82e2ab4c42 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(Clone, Copy, Debug)] +pub struct RefPtr(T); +#[repr(C)] +pub struct HasRefPtr { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub refptr_member: RefPtr>, +} +pub type HasRefPtr_TypedefOfT = T; +impl Default for HasRefPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-648-derive-debug-with-padding.rs b/bindgen-tests/tests/expectations/tests/issue-648-derive-debug-with-padding.rs new file mode 100644 index 0000000000..5d87159f97 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-648-derive-debug-with-padding.rs @@ -0,0 +1,59 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** We emit a `[u8; 63usize]` padding field for this struct, which cannot derive + Debug/Hash because 63 is over the hard coded limit.*/ +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct NoDebug { + pub c: ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoDebug"][::std::mem::size_of::() - 64usize]; + ["Alignment of NoDebug"][::std::mem::align_of::() - 64usize]; + ["Offset of field: NoDebug::c"][::std::mem::offset_of!(NoDebug, c) - 0usize]; +}; +impl Default for NoDebug { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/** This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive + Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because + we determine Debug derive-ability before we compute padding, which happens at + codegen.*/ +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ShouldDeriveDebugButDoesNot { + pub c: [::std::os::raw::c_char; 32usize], + pub d: ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ShouldDeriveDebugButDoesNot", + ][::std::mem::size_of::() - 64usize]; + [ + "Alignment of ShouldDeriveDebugButDoesNot", + ][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: ShouldDeriveDebugButDoesNot::c", + ][::std::mem::offset_of!(ShouldDeriveDebugButDoesNot, c) - 0usize]; + [ + "Offset of field: ShouldDeriveDebugButDoesNot::d", + ][::std::mem::offset_of!(ShouldDeriveDebugButDoesNot, d) - 32usize]; +}; +impl Default for ShouldDeriveDebugButDoesNot { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/issue-654-struct-fn-collision.rs b/bindgen-tests/tests/expectations/tests/issue-654-struct-fn-collision.rs similarity index 77% rename from tests/expectations/tests/issue-654-struct-fn-collision.rs rename to bindgen-tests/tests/expectations/tests/issue-654-struct-fn-collision.rs index fbd8cca3ec..6bf02be74e 100644 --- a/tests/expectations/tests/issue-654-struct-fn-collision.rs +++ b/bindgen-tests/tests/expectations/tests/issue-654-struct-fn-collision.rs @@ -1,12 +1,9 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct foo { _unused: [u8; 0], } -extern "C" { +unsafe extern "C" { pub fn foo() -> ::std::os::raw::c_int; } diff --git a/bindgen-tests/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs b/bindgen-tests/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs new file mode 100644 index 0000000000..2e68628323 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs @@ -0,0 +1,46 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RefPtr { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub a: T, +} +impl Default for RefPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsMainThreadPtrHolder { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub a: T, +} +impl Default for nsMainThreadPtrHolder { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsMainThreadPtrHandle { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub mPtr: RefPtr>, +} +impl Default for nsMainThreadPtrHandle { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-662-part-2.rs b/bindgen-tests/tests/expectations/tests/issue-662-part-2.rs new file mode 100644 index 0000000000..9ddcdc5e8d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-662-part-2.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(Clone, Copy, Debug)] +pub struct RefPtr(T); +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsMainThreadPtrHolder { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub a: T, +} +impl Default for nsMainThreadPtrHolder { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct nsMainThreadPtrHandle { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub mPtr: RefPtr>, +} +impl Default for nsMainThreadPtrHandle { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-674-1.rs b/bindgen-tests/tests/expectations/tests/issue-674-1.rs new file mode 100644 index 0000000000..1a3dce44d0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-674-1.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod mozilla { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Maybe { + pub _address: u8, + } + pub type Maybe_ValueType = T; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct CapturingContentInfo { + pub a: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of CapturingContentInfo", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of CapturingContentInfo", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: CapturingContentInfo::a", + ][::std::mem::offset_of!(CapturingContentInfo, a) - 0usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-674-2.rs b/bindgen-tests/tests/expectations/tests/issue-674-2.rs new file mode 100644 index 0000000000..980928fe97 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-674-2.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod JS { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Rooted { + pub _address: u8, + } + pub type Rooted_ElementType = T; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct c { + pub b: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of c"][::std::mem::size_of::() - 1usize]; + ["Alignment of c"][::std::mem::align_of::() - 1usize]; + ["Offset of field: c::b"][::std::mem::offset_of!(c, b) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct B { + pub a: root::c, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of B"][::std::mem::size_of::() - 1usize]; + ["Alignment of B"][::std::mem::align_of::() - 1usize]; + ["Offset of field: B::a"][::std::mem::offset_of!(B, a) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct StaticRefPtr { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of template specialization: StaticRefPtr_open0_B_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: StaticRefPtr_open0_B_close0", + ][::std::mem::align_of::() - 1usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-674-3.rs b/bindgen-tests/tests/expectations/tests/issue-674-3.rs new file mode 100644 index 0000000000..4e2f26a46f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-674-3.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct nsRefPtrHashtable { + pub _address: u8, + } + pub type nsRefPtrHashtable_UserDataType = *mut PtrType; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct a { + pub b: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of a"][::std::mem::size_of::() - 1usize]; + ["Alignment of a"][::std::mem::align_of::() - 1usize]; + ["Offset of field: a::b"][::std::mem::offset_of!(a, b) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct nsCSSValue { + pub c: root::a, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of nsCSSValue"][::std::mem::size_of::() - 1usize]; + ["Alignment of nsCSSValue"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: nsCSSValue::c", + ][::std::mem::offset_of!(nsCSSValue, c) - 0usize]; + }; +} diff --git a/tests/expectations/tests/issue-677-nested-ns-specifier.rs b/bindgen-tests/tests/expectations/tests/issue-677-nested-ns-specifier.rs similarity index 90% rename from tests/expectations/tests/issue-677-nested-ns-specifier.rs rename to bindgen-tests/tests/expectations/tests/issue-677-nested-ns-specifier.rs index c3fb04061d..34ec99688a 100644 --- a/tests/expectations/tests/issue-677-nested-ns-specifier.rs +++ b/bindgen-tests/tests/expectations/tests/issue-677-nested-ns-specifier.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] pub mod root { #[allow(unused_imports)] diff --git a/bindgen-tests/tests/expectations/tests/issue-691-template-parameter-virtual.rs b/bindgen-tests/tests/expectations/tests/issue-691-template-parameter-virtual.rs new file mode 100644 index 0000000000..1313d61168 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-691-template-parameter-virtual.rs @@ -0,0 +1,59 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct VirtualMethods__bindgen_vtable {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VirtualMethods { + pub vtable_: *const VirtualMethods__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of VirtualMethods"][::std::mem::size_of::() - 8usize]; + ["Alignment of VirtualMethods"][::std::mem::align_of::() - 8usize]; +}; +impl Default for VirtualMethods { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Set { + pub bar: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ServoElementSnapshotTable { + pub _base: Set, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ServoElementSnapshotTable", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of ServoElementSnapshotTable", + ][::std::mem::align_of::() - 4usize]; +}; +impl Default for ServoElementSnapshotTable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Set_open0_VirtualMethods_close0", + ][::std::mem::size_of::() - 4usize]; + [ + "Align of template specialization: Set_open0_VirtualMethods_close0", + ][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-710-must-use-type.rs b/bindgen-tests/tests/expectations/tests/issue-710-must-use-type.rs new file mode 100644 index 0000000000..d7006dd011 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-710-must-use-type.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[must_use] +pub struct A { + _unused: [u8; 0], +} +///
+#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[must_use] +pub struct B { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs new file mode 100644 index 0000000000..bc1951e7d1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs @@ -0,0 +1,351 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(target_os = "windows"))] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _bindgen_align: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 32usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 32usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; +}; +impl Foo { + #[inline] + pub fn m_bitfield(&self) -> ::std::os::raw::c_ulong { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 64u8) as u64) } + } + #[inline] + pub fn set_m_bitfield(&mut self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 64u8, val as u64) + } + } + #[inline] + pub unsafe fn m_bitfield_raw(this: *const Self) -> ::std::os::raw::c_ulong { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 64u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_m_bitfield_raw(this: *mut Self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 64u8, + val as u64, + ) + } + } + #[inline] + pub fn m_bar(&self) -> ::std::os::raw::c_ulong { + unsafe { ::std::mem::transmute(self._bitfield_1.get(64usize, 64u8) as u64) } + } + #[inline] + pub fn set_m_bar(&mut self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(64usize, 64u8, val as u64) + } + } + #[inline] + pub unsafe fn m_bar_raw(this: *const Self) -> ::std::os::raw::c_ulong { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 64usize, 64u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_m_bar_raw(this: *mut Self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 64usize, + 64u8, + val as u64, + ) + } + } + #[inline] + pub fn foo(&self) -> ::std::os::raw::c_ulong { + unsafe { ::std::mem::transmute(self._bitfield_1.get(128usize, 1u8) as u64) } + } + #[inline] + pub fn set_foo(&mut self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(128usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn foo_raw(this: *const Self) -> ::std::os::raw::c_ulong { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 128usize, 1u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_foo_raw(this: *mut Self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 128usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bar(&self) -> ::std::os::raw::c_ulong { + unsafe { ::std::mem::transmute(self._bitfield_1.get(192usize, 64u8) as u64) } + } + #[inline] + pub fn set_bar(&mut self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(192usize, 64u8, val as u64) + } + } + #[inline] + pub unsafe fn bar_raw(this: *const Self) -> ::std::os::raw::c_ulong { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 192usize, 64u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_bar_raw(this: *mut Self, val: ::std::os::raw::c_ulong) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 32usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 192usize, + 64u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + m_bitfield: ::std::os::raw::c_ulong, + m_bar: ::std::os::raw::c_ulong, + foo: ::std::os::raw::c_ulong, + bar: ::std::os::raw::c_ulong, + ) -> __BindgenBitfieldUnit<[u8; 32usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 32usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 64u8, + { + let m_bitfield: u64 = unsafe { ::std::mem::transmute(m_bitfield) }; + m_bitfield as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 64usize, + 64u8, + { + let m_bar: u64 = unsafe { ::std::mem::transmute(m_bar) }; + m_bar as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 128usize, + 1u8, + { + let foo: u64 = unsafe { ::std::mem::transmute(foo) }; + foo as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 192usize, + 64u8, + { + let bar: u64 = unsafe { ::std::mem::transmute(bar) }; + bar as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-743.rs b/bindgen-tests/tests/expectations/tests/issue-743.rs new file mode 100644 index 0000000000..af3eb5bf6e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-743.rs @@ -0,0 +1,225 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct S { + pub p: *mut ::std::os::raw::c_void, + pub b: bool, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub __bindgen_padding_0: [u8; 5usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S"][::std::mem::size_of::() - 16usize]; + ["Alignment of S"][::std::mem::align_of::() - 8usize]; + ["Offset of field: S::p"][::std::mem::offset_of!(S, p) - 0usize]; + ["Offset of field: S::b"][::std::mem::offset_of!(S, b) - 8usize]; +}; +impl Default for S { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl S { + #[inline] + pub fn u(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) } + } + #[inline] + pub fn set_u(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn u_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 16u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_u_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + u: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 16u8, + { + let u: u32 = unsafe { ::std::mem::transmute(u) }; + u as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-753.rs b/bindgen-tests/tests/expectations/tests/issue-753.rs new file mode 100644 index 0000000000..3119ec569e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-753.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const CONST: u32 = 5; +pub const OTHER_CONST: u32 = 6; +pub const LARGE_CONST: u32 = 1536; diff --git a/bindgen-tests/tests/expectations/tests/issue-769-bad-instantiation-test.rs b/bindgen-tests/tests/expectations/tests/issue-769-bad-instantiation-test.rs new file mode 100644 index 0000000000..59a1d9afa3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-769-bad-instantiation-test.rs @@ -0,0 +1,40 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, + } + impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + pub type AutoValueVector_Alias = ::std::os::raw::c_int; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of template specialization: Rooted_open0_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: Rooted_open0_int_close0", + ][::std::mem::align_of::>() - 4usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of template specialization: Rooted_open0_AutoValueVector_Alias_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: Rooted_open0_AutoValueVector_Alias_close0", + ][::std::mem::align_of::>() - 4usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-801-opaque-sloppiness.rs b/bindgen-tests/tests/expectations/tests/issue-801-opaque-sloppiness.rs new file mode 100644 index 0000000000..90eb048640 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-801-opaque-sloppiness.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct A { + _unused: [u8; 0], +} +#[repr(C)] +#[repr(align(1))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct B { + pub _bindgen_opaque_blob: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 1usize]; + ["Alignment of B"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1B1aE"] + pub static mut B_a: A; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct C { + pub b: B, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 1usize]; + ["Alignment of C"][::std::mem::align_of::() - 1usize]; + ["Offset of field: C::b"][::std::mem::offset_of!(C, b) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs b/bindgen-tests/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs new file mode 100644 index 0000000000..3d3ee5e590 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs @@ -0,0 +1,79 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Pupper { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Pupper"][::std::mem::size_of::() - 1usize]; + ["Alignment of Pupper"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Doggo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Doggo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Doggo"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct SuchWow { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of SuchWow"][::std::mem::size_of::() - 1usize]; + ["Alignment of SuchWow"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[repr(align(1))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Opaque { + pub _bindgen_opaque_blob: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Opaque"][::std::mem::size_of::() - 1usize]; + ["Alignment of Opaque"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN6Opaque17eleven_out_of_tenEv"] + pub fn Opaque_eleven_out_of_ten(this: *mut Opaque) -> SuchWow; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN6OpaqueC1E6Pupper"] + pub fn Opaque_Opaque(this: *mut Opaque, pup: Pupper); +} +impl Opaque { + #[inline] + pub unsafe fn eleven_out_of_ten(&mut self) -> SuchWow { + Opaque_eleven_out_of_ten(self) + } + #[inline] + pub unsafe fn new(pup: Pupper) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + Opaque_Opaque(__bindgen_tmp.as_mut_ptr(), pup); + __bindgen_tmp.assume_init() + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN6Opaque11MAJESTIC_AFE"] + pub static mut Opaque_MAJESTIC_AF: Doggo; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Allowlisted { + pub some_member: Opaque, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Allowlisted"][::std::mem::size_of::() - 1usize]; + ["Alignment of Allowlisted"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: Allowlisted::some_member", + ][::std::mem::offset_of!(Allowlisted, some_member) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-816.rs b/bindgen-tests/tests/expectations/tests/issue-816.rs new file mode 100644 index 0000000000..b1494afede --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-816.rs @@ -0,0 +1,2052 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct capabilities { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of capabilities"][::std::mem::size_of::() - 16usize]; + ["Alignment of capabilities"][::std::mem::align_of::() - 4usize]; +}; +impl capabilities { + #[inline] + pub fn bit_1(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_1(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_1_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_1_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_2(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_2(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_2_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_2_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_3(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_3(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_3_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_3_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_4(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_4(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_4_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_4_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_5(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_5(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_5_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_5_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_6(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_6(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_6_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 5usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_6_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 5usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_7(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_7(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_7_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 6usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_7_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 6usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_8(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_8(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_8_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_8_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_9(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_9(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_9_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_9_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_10(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_10(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_10_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_10_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_11(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_11(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(10usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_11_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 10usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_11_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 10usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_12(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_12(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(11usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_12_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 11usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_12_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 11usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_13(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_13(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_13_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 12usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_13_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 12usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_14(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_14(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(13usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_14_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 13usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_14_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 13usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_15(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_15(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(14usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_15_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 14usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_15_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 14usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_16(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_16(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(15usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_16_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 15usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_16_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 15usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_17(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_17(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_17_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_17_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_18(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(17usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_18(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(17usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_18_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 17usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_18_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 17usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_19(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(18usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_19(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(18usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_19_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 18usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_19_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 18usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_20(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_20(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(19usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_20_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 19usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_20_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 19usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_21(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_21(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(20usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_21_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 20usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_21_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 20usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_22(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_22(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(21usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_22_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 21usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_22_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 21usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_23(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(22usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_23(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(22usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_23_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 22usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_23_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 22usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_24(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(23usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_24(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(23usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_24_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 23usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_24_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 23usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_25(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_25(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_25_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_25_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_26(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(25usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_26(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(25usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_26_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 25usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_26_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 25usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_27(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(26usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_27(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(26usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_27_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 26usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_27_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 26usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_28(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(27usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_28(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(27usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_28_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 27usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_28_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 27usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_29(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_29(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(28usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_29_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 28usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_29_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 28usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_30(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_30(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(29usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_30_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 29usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_30_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 29usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_31(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_31(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(30usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_31_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 30usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_31_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 30usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_32(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_32(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(31usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_32_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 31usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_32_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 31usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_33(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_33(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(32usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_33_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 32usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_33_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 32usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_34(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(33usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_34(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(33usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_34_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 33usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_34_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 33usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_35(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(34usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_35(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(34usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_35_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 34usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_35_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 34usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_36(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(35usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_36(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(35usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_36_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 35usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_36_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 35usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_37(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(36usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_37(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(36usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_37_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 36usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_37_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 36usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_38(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(37usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_38(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(37usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_38_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 37usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_38_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 37usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_39(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(38usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_39(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(38usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_39_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 38usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_39_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 38usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_40(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(39usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_40(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(39usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_40_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 39usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_40_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 39usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn bit_41(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 1u8) as u32) } + } + #[inline] + pub fn set_bit_41(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(40usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bit_41_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 40usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bit_41_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 16usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 40usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + bit_1: ::std::os::raw::c_uint, + bit_2: ::std::os::raw::c_uint, + bit_3: ::std::os::raw::c_uint, + bit_4: ::std::os::raw::c_uint, + bit_5: ::std::os::raw::c_uint, + bit_6: ::std::os::raw::c_uint, + bit_7: ::std::os::raw::c_uint, + bit_8: ::std::os::raw::c_uint, + bit_9: ::std::os::raw::c_uint, + bit_10: ::std::os::raw::c_uint, + bit_11: ::std::os::raw::c_uint, + bit_12: ::std::os::raw::c_uint, + bit_13: ::std::os::raw::c_uint, + bit_14: ::std::os::raw::c_uint, + bit_15: ::std::os::raw::c_uint, + bit_16: ::std::os::raw::c_uint, + bit_17: ::std::os::raw::c_uint, + bit_18: ::std::os::raw::c_uint, + bit_19: ::std::os::raw::c_uint, + bit_20: ::std::os::raw::c_uint, + bit_21: ::std::os::raw::c_uint, + bit_22: ::std::os::raw::c_uint, + bit_23: ::std::os::raw::c_uint, + bit_24: ::std::os::raw::c_uint, + bit_25: ::std::os::raw::c_uint, + bit_26: ::std::os::raw::c_uint, + bit_27: ::std::os::raw::c_uint, + bit_28: ::std::os::raw::c_uint, + bit_29: ::std::os::raw::c_uint, + bit_30: ::std::os::raw::c_uint, + bit_31: ::std::os::raw::c_uint, + bit_32: ::std::os::raw::c_uint, + bit_33: ::std::os::raw::c_uint, + bit_34: ::std::os::raw::c_uint, + bit_35: ::std::os::raw::c_uint, + bit_36: ::std::os::raw::c_uint, + bit_37: ::std::os::raw::c_uint, + bit_38: ::std::os::raw::c_uint, + bit_39: ::std::os::raw::c_uint, + bit_40: ::std::os::raw::c_uint, + bit_41: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 16usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let bit_1: u32 = unsafe { ::std::mem::transmute(bit_1) }; + bit_1 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let bit_2: u32 = unsafe { ::std::mem::transmute(bit_2) }; + bit_2 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let bit_3: u32 = unsafe { ::std::mem::transmute(bit_3) }; + bit_3 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 1u8, + { + let bit_4: u32 = unsafe { ::std::mem::transmute(bit_4) }; + bit_4 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 1u8, + { + let bit_5: u32 = unsafe { ::std::mem::transmute(bit_5) }; + bit_5 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 5usize, + 1u8, + { + let bit_6: u32 = unsafe { ::std::mem::transmute(bit_6) }; + bit_6 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 1u8, + { + let bit_7: u32 = unsafe { ::std::mem::transmute(bit_7) }; + bit_7 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 1u8, + { + let bit_8: u32 = unsafe { ::std::mem::transmute(bit_8) }; + bit_8 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 1u8, + { + let bit_9: u32 = unsafe { ::std::mem::transmute(bit_9) }; + bit_9 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 1u8, + { + let bit_10: u32 = unsafe { ::std::mem::transmute(bit_10) }; + bit_10 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 10usize, + 1u8, + { + let bit_11: u32 = unsafe { ::std::mem::transmute(bit_11) }; + bit_11 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 11usize, + 1u8, + { + let bit_12: u32 = unsafe { ::std::mem::transmute(bit_12) }; + bit_12 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 12usize, + 1u8, + { + let bit_13: u32 = unsafe { ::std::mem::transmute(bit_13) }; + bit_13 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 13usize, + 1u8, + { + let bit_14: u32 = unsafe { ::std::mem::transmute(bit_14) }; + bit_14 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 1u8, + { + let bit_15: u32 = unsafe { ::std::mem::transmute(bit_15) }; + bit_15 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 15usize, + 1u8, + { + let bit_16: u32 = unsafe { ::std::mem::transmute(bit_16) }; + bit_16 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 1u8, + { + let bit_17: u32 = unsafe { ::std::mem::transmute(bit_17) }; + bit_17 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 17usize, + 1u8, + { + let bit_18: u32 = unsafe { ::std::mem::transmute(bit_18) }; + bit_18 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 18usize, + 1u8, + { + let bit_19: u32 = unsafe { ::std::mem::transmute(bit_19) }; + bit_19 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 19usize, + 1u8, + { + let bit_20: u32 = unsafe { ::std::mem::transmute(bit_20) }; + bit_20 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 20usize, + 1u8, + { + let bit_21: u32 = unsafe { ::std::mem::transmute(bit_21) }; + bit_21 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 21usize, + 1u8, + { + let bit_22: u32 = unsafe { ::std::mem::transmute(bit_22) }; + bit_22 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 22usize, + 1u8, + { + let bit_23: u32 = unsafe { ::std::mem::transmute(bit_23) }; + bit_23 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 23usize, + 1u8, + { + let bit_24: u32 = unsafe { ::std::mem::transmute(bit_24) }; + bit_24 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 1u8, + { + let bit_25: u32 = unsafe { ::std::mem::transmute(bit_25) }; + bit_25 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 25usize, + 1u8, + { + let bit_26: u32 = unsafe { ::std::mem::transmute(bit_26) }; + bit_26 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 26usize, + 1u8, + { + let bit_27: u32 = unsafe { ::std::mem::transmute(bit_27) }; + bit_27 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 27usize, + 1u8, + { + let bit_28: u32 = unsafe { ::std::mem::transmute(bit_28) }; + bit_28 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 28usize, + 1u8, + { + let bit_29: u32 = unsafe { ::std::mem::transmute(bit_29) }; + bit_29 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 29usize, + 1u8, + { + let bit_30: u32 = unsafe { ::std::mem::transmute(bit_30) }; + bit_30 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 30usize, + 1u8, + { + let bit_31: u32 = unsafe { ::std::mem::transmute(bit_31) }; + bit_31 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 31usize, + 1u8, + { + let bit_32: u32 = unsafe { ::std::mem::transmute(bit_32) }; + bit_32 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 32usize, + 1u8, + { + let bit_33: u32 = unsafe { ::std::mem::transmute(bit_33) }; + bit_33 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 33usize, + 1u8, + { + let bit_34: u32 = unsafe { ::std::mem::transmute(bit_34) }; + bit_34 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 34usize, + 1u8, + { + let bit_35: u32 = unsafe { ::std::mem::transmute(bit_35) }; + bit_35 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 35usize, + 1u8, + { + let bit_36: u32 = unsafe { ::std::mem::transmute(bit_36) }; + bit_36 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 36usize, + 1u8, + { + let bit_37: u32 = unsafe { ::std::mem::transmute(bit_37) }; + bit_37 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 37usize, + 1u8, + { + let bit_38: u32 = unsafe { ::std::mem::transmute(bit_38) }; + bit_38 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 38usize, + 1u8, + { + let bit_39: u32 = unsafe { ::std::mem::transmute(bit_39) }; + bit_39 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 39usize, + 1u8, + { + let bit_40: u32 = unsafe { ::std::mem::transmute(bit_40) }; + bit_40 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 40usize, + 1u8, + { + let bit_41: u32 = unsafe { ::std::mem::transmute(bit_41) }; + bit_41 as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs b/bindgen-tests/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs new file mode 100644 index 0000000000..a367e2e0e1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type Foo_self_type = u8; diff --git a/bindgen-tests/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs b/bindgen-tests/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs new file mode 100644 index 0000000000..551dff82cf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-833-1.rs b/bindgen-tests/tests/expectations/tests/issue-833-1.rs new file mode 100644 index 0000000000..5aa8c3078b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-833-1.rs @@ -0,0 +1,8 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct nsTArray { + pub hdr: *const (), +} +unsafe extern "C" { + pub fn func() -> *mut nsTArray; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-833-2.rs b/bindgen-tests/tests/expectations/tests/issue-833-2.rs new file mode 100644 index 0000000000..b8ef2f8554 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-833-2.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct nsTArray { + pub _address: u8, +} diff --git a/tests/expectations/tests/issue-833.rs b/bindgen-tests/tests/expectations/tests/issue-833.rs similarity index 76% rename from tests/expectations/tests/issue-833.rs rename to bindgen-tests/tests/expectations/tests/issue-833.rs index 4ee4602ab9..9698fdb479 100644 --- a/tests/expectations/tests/issue-833.rs +++ b/bindgen-tests/tests/expectations/tests/issue-833.rs @@ -1,13 +1,8 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - #[repr(C)] pub struct nsTArray { pub hdr: *const T, } - -extern "C" { +unsafe extern "C" { pub fn func() -> *mut nsTArray<::std::os::raw::c_int>; } diff --git a/bindgen-tests/tests/expectations/tests/issue-834.rs b/bindgen-tests/tests/expectations/tests/issue-834.rs new file mode 100644 index 0000000000..4119a450e0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-834.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct U { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of U"][::std::mem::size_of::() - 1usize]; + ["Alignment of U"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/issue-848-replacement-system-include.rs b/bindgen-tests/tests/expectations/tests/issue-848-replacement-system-include.rs new file mode 100644 index 0000000000..6beeae69d8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-848-replacement-system-include.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** This is intended to replace another type, but won't if we treat this include + as a system include, because clang doesn't parse comments there. + + See #848. + +
*/ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m: *mut T, +} +impl Default for nsTArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + pub fn func() -> *mut nsTArray<::std::os::raw::c_int>; +} diff --git a/bindgen-tests/tests/expectations/tests/issue-888-enum-var-decl-jump.rs b/bindgen-tests/tests/expectations/tests/issue-888-enum-var-decl-jump.rs new file mode 100644 index 0000000000..023c8695e3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-888-enum-var-decl-jump.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod Halide { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Type { + pub _address: u8, + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN6Halide4Type1bE"] + pub static mut Type_b: root::a; + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Type"][::std::mem::size_of::() - 1usize]; + ["Alignment of Type"][::std::mem::align_of::() - 1usize]; + }; + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum a { + __bindgen_cannot_repr_c_on_empty_enum = 0, + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-944-derive-copy-and-blocklisting.rs b/bindgen-tests/tests/expectations/tests/issue-944-derive-copy-and-blocklisting.rs new file mode 100644 index 0000000000..5e8dde04e3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-944-derive-copy-and-blocklisting.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct BlocklistMe(u8); +/// Because this type contains a blocklisted type, it should not derive Copy. +#[repr(C)] +pub struct ShouldNotBeCopy { + pub a: BlocklistMe, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ShouldNotBeCopy"][::std::mem::size_of::() - 1usize]; + ["Alignment of ShouldNotBeCopy"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ShouldNotBeCopy::a", + ][::std::mem::offset_of!(ShouldNotBeCopy, a) - 0usize]; +}; +impl Default for ShouldNotBeCopy { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-946.rs b/bindgen-tests/tests/expectations/tests/issue-946.rs new file mode 100644 index 0000000000..bdd56c0326 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-946.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo {} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 0usize]; + ["Alignment of foo"][::std::mem::align_of::() - 1usize]; +}; +pub type bar = foo; diff --git a/bindgen-tests/tests/expectations/tests/issue_311.rs b/bindgen-tests/tests/expectations/tests/issue_311.rs new file mode 100644 index 0000000000..2e0114e43e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue_311.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct jsval_layout { + pub __bindgen_anon_1: root::jsval_layout__bindgen_ty_1, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct jsval_layout__bindgen_ty_1 { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of jsval_layout__bindgen_ty_1", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of jsval_layout__bindgen_ty_1", + ][::std::mem::align_of::() - 1usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of jsval_layout"][::std::mem::size_of::() - 1usize]; + ["Alignment of jsval_layout"][::std::mem::align_of::() - 1usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/issue_315.rs b/bindgen-tests/tests/expectations/tests/issue_315.rs new file mode 100644 index 0000000000..cecdccc2aa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue_315.rs @@ -0,0 +1,3 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+pub type c
= a; diff --git a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs new file mode 100644 index 0000000000..dc0ef8ed7f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs @@ -0,0 +1,483 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +pub const JSVAL_TAG_SHIFT: u32 = 47; +pub const JSVAL_PAYLOAD_MASK: u64 = 140737488355327; +pub const JSVAL_TAG_MASK: i64 = -140737488355328; +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum JSValueType { + JSVAL_TYPE_DOUBLE = 0, + JSVAL_TYPE_INT32 = 1, + JSVAL_TYPE_UNDEFINED = 2, + JSVAL_TYPE_BOOLEAN = 3, + JSVAL_TYPE_MAGIC = 4, + JSVAL_TYPE_STRING = 5, + JSVAL_TYPE_SYMBOL = 6, + JSVAL_TYPE_NULL = 7, + JSVAL_TYPE_OBJECT = 8, + JSVAL_TYPE_UNKNOWN = 32, + JSVAL_TYPE_MISSING = 33, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum JSValueTag { + JSVAL_TAG_MAX_DOUBLE = 131056, + JSVAL_TAG_INT32 = 131057, + JSVAL_TAG_UNDEFINED = 131058, + JSVAL_TAG_STRING = 131061, + JSVAL_TAG_SYMBOL = 131062, + JSVAL_TAG_BOOLEAN = 131059, + JSVAL_TAG_MAGIC = 131060, + JSVAL_TAG_NULL = 131063, + JSVAL_TAG_OBJECT = 131064, +} +#[repr(u64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum JSValueShiftedTag { + JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663, + JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696, + JSVAL_SHIFTED_TAG_UNDEFINED = 18444773748872577024, + JSVAL_SHIFTED_TAG_STRING = 18445195961337643008, + JSVAL_SHIFTED_TAG_SYMBOL = 18445336698825998336, + JSVAL_SHIFTED_TAG_BOOLEAN = 18444914486360932352, + JSVAL_SHIFTED_TAG_MAGIC = 18445055223849287680, + JSVAL_SHIFTED_TAG_NULL = 18445477436314353664, + JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum JSWhyMagic { + /// a hole in a native object's elements + JS_ELEMENTS_HOLE = 0, + /// there is not a pending iterator value + JS_NO_ITER_VALUE = 1, + /// exception value thrown when closing a generator + JS_GENERATOR_CLOSING = 2, + /// compiler sentinel value + JS_NO_CONSTANT = 3, + /// used in debug builds to catch tracing errors + JS_THIS_POISON = 4, + /// used in debug builds to catch tracing errors + JS_ARG_POISON = 5, + /// an empty subnode in the AST serializer + JS_SERIALIZE_NO_NODE = 6, + /// lazy arguments value on the stack + JS_LAZY_ARGUMENTS = 7, + /// optimized-away 'arguments' value + JS_OPTIMIZED_ARGUMENTS = 8, + /// magic value passed to natives to indicate construction + JS_IS_CONSTRUCTING = 9, + /// arguments.callee has been overwritten + JS_OVERWRITTEN_CALLEE = 10, + /// value of static block object slot + JS_BLOCK_NEEDS_CLONE = 11, + /// see class js::HashableValue + JS_HASH_KEY_EMPTY = 12, + /// error while running Ion code + JS_ION_ERROR = 13, + /// missing recover instruction result + JS_ION_BAILOUT = 14, + /// optimized out slot + JS_OPTIMIZED_OUT = 15, + /// uninitialized lexical bindings that produce ReferenceError on touch. + JS_UNINITIALIZED_LEXICAL = 16, + /// for local use + JS_GENERIC_MAGIC = 17, + /// for local use + JS_WHY_MAGIC_COUNT = 18, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union jsval_layout { + pub asBits: u64, + pub debugView: jsval_layout__bindgen_ty_1, + pub s: jsval_layout__bindgen_ty_2, + pub asDouble: f64, + pub asPtr: *mut ::std::os::raw::c_void, + pub asWord: usize, + pub asUIntPtr: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct jsval_layout__bindgen_ty_1 { + pub _bindgen_align: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of jsval_layout__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of jsval_layout__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for jsval_layout__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl jsval_layout__bindgen_ty_1 { + #[inline] + pub fn payload47(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 47u8) as u64) } + } + #[inline] + pub fn set_payload47(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 47u8, val as u64) + } + } + #[inline] + pub unsafe fn payload47_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 47u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_payload47_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 47u8, + val as u64, + ) + } + } + #[inline] + pub fn tag(&self) -> JSValueTag { + unsafe { ::std::mem::transmute(self._bitfield_1.get(47usize, 17u8) as u32) } + } + #[inline] + pub fn set_tag(&mut self, val: JSValueTag) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(47usize, 17u8, val as u64) + } + } + #[inline] + pub unsafe fn tag_raw(this: *const Self) -> JSValueTag { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 47usize, 17u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_tag_raw(this: *mut Self, val: JSValueTag) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 47usize, + 17u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + payload47: u64, + tag: JSValueTag, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 47u8, + { + let payload47: u64 = unsafe { ::std::mem::transmute(payload47) }; + payload47 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 47usize, + 17u8, + { + let tag: u32 = unsafe { ::std::mem::transmute(tag) }; + tag as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct jsval_layout__bindgen_ty_2 { + pub payload: jsval_layout__bindgen_ty_2__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union jsval_layout__bindgen_ty_2__bindgen_ty_1 { + pub i32_: i32, + pub u32_: u32, + pub why: JSWhyMagic, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of jsval_layout__bindgen_ty_2__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of jsval_layout__bindgen_ty_2__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: jsval_layout__bindgen_ty_2__bindgen_ty_1::i32_", + ][::std::mem::offset_of!(jsval_layout__bindgen_ty_2__bindgen_ty_1, i32_) - 0usize]; + [ + "Offset of field: jsval_layout__bindgen_ty_2__bindgen_ty_1::u32_", + ][::std::mem::offset_of!(jsval_layout__bindgen_ty_2__bindgen_ty_1, u32_) - 0usize]; + [ + "Offset of field: jsval_layout__bindgen_ty_2__bindgen_ty_1::why", + ][::std::mem::offset_of!(jsval_layout__bindgen_ty_2__bindgen_ty_1, why) - 0usize]; +}; +impl Default for jsval_layout__bindgen_ty_2__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of jsval_layout__bindgen_ty_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of jsval_layout__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: jsval_layout__bindgen_ty_2::payload", + ][::std::mem::offset_of!(jsval_layout__bindgen_ty_2, payload) - 0usize]; +}; +impl Default for jsval_layout__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of jsval_layout"][::std::mem::size_of::() - 8usize]; + ["Alignment of jsval_layout"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: jsval_layout::asBits", + ][::std::mem::offset_of!(jsval_layout, asBits) - 0usize]; + [ + "Offset of field: jsval_layout::debugView", + ][::std::mem::offset_of!(jsval_layout, debugView) - 0usize]; + [ + "Offset of field: jsval_layout::s", + ][::std::mem::offset_of!(jsval_layout, s) - 0usize]; + [ + "Offset of field: jsval_layout::asDouble", + ][::std::mem::offset_of!(jsval_layout, asDouble) - 0usize]; + [ + "Offset of field: jsval_layout::asPtr", + ][::std::mem::offset_of!(jsval_layout, asPtr) - 0usize]; + [ + "Offset of field: jsval_layout::asWord", + ][::std::mem::offset_of!(jsval_layout, asWord) - 0usize]; + [ + "Offset of field: jsval_layout::asUIntPtr", + ][::std::mem::offset_of!(jsval_layout, asUIntPtr) - 0usize]; +}; +impl Default for jsval_layout { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Value { + pub data: jsval_layout, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Value"][::std::mem::size_of::() - 8usize]; + ["Alignment of Value"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Value::data"][::std::mem::offset_of!(Value, data) - 0usize]; +}; +impl Default for Value { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/keywords.rs b/bindgen-tests/tests/expectations/tests/keywords.rs new file mode 100644 index 0000000000..0a55ee0463 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/keywords.rs @@ -0,0 +1,225 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}u8"] + pub static mut u8_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}u16"] + pub static mut u16_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}u32"] + pub static mut u32_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}u64"] + pub static mut u64_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}i8"] + pub static mut i8_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}i16"] + pub static mut i16_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}i32"] + pub static mut i32_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}i64"] + pub static mut i64_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}f32"] + pub static mut f32_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}f64"] + pub static mut f64_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}usize"] + pub static mut usize_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}isize"] + pub static mut isize_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}bool"] + pub static mut bool_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}str"] + pub static mut str_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}dyn"] + pub static mut dyn_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}as"] + pub static mut as_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}async"] + pub static mut async_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}await"] + pub static mut await_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}box"] + pub static mut box_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}crate"] + pub static mut crate_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}false"] + pub static mut false_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}fn"] + pub static mut fn_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}gen"] + pub static mut gen_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}impl"] + pub static mut impl_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}in"] + pub static mut in_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}let"] + pub static mut let_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}loop"] + pub static mut loop_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}match"] + pub static mut match_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}mod"] + pub static mut mod_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}move"] + pub static mut move_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}mut"] + pub static mut mut_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}pub"] + pub static mut pub_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}ref"] + pub static mut ref_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}self"] + pub static mut self_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}Self"] + pub static mut Self_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}super"] + pub static mut super_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}trait"] + pub static mut trait_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}true"] + pub static mut true_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}try"] + pub static mut try_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}type"] + pub static mut type_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}unsafe"] + pub static mut unsafe_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}use"] + pub static mut use_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}where"] + pub static mut where_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}abstract"] + pub static mut abstract_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}alignof"] + pub static mut alignof_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}become"] + pub static mut become_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}final"] + pub static mut final_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}macro"] + pub static mut macro_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}offsetof"] + pub static mut offsetof_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}override"] + pub static mut override_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}priv"] + pub static mut priv_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}proc"] + pub static mut proc_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}pure"] + pub static mut pure_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}unsized"] + pub static mut unsized_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}virtual"] + pub static mut virtual_: ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}yield"] + pub static mut yield_: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/layout.rs b/bindgen-tests/tests/expectations/tests/layout.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/layout_align.rs b/bindgen-tests/tests/expectations/tests/layout_align.rs new file mode 100644 index 0000000000..a942adb8f2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_align.rs @@ -0,0 +1,385 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug)] +pub struct rte_kni_fifo { + ///< Next position to be written + pub write: ::std::os::raw::c_uint, + ///< Next position to be read + pub read: ::std::os::raw::c_uint, + ///< Circular buffer length + pub len: ::std::os::raw::c_uint, + ///< Pointer size - for 32/64 bit OS + pub elem_size: ::std::os::raw::c_uint, + ///< The buffer contains mbuf pointers + pub buffer: __IncompleteArrayField<*mut ::std::os::raw::c_void>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_kni_fifo"][::std::mem::size_of::() - 16usize]; + ["Alignment of rte_kni_fifo"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_kni_fifo::write", + ][::std::mem::offset_of!(rte_kni_fifo, write) - 0usize]; + [ + "Offset of field: rte_kni_fifo::read", + ][::std::mem::offset_of!(rte_kni_fifo, read) - 4usize]; + [ + "Offset of field: rte_kni_fifo::len", + ][::std::mem::offset_of!(rte_kni_fifo, len) - 8usize]; + [ + "Offset of field: rte_kni_fifo::elem_size", + ][::std::mem::offset_of!(rte_kni_fifo, elem_size) - 12usize]; + [ + "Offset of field: rte_kni_fifo::buffer", + ][::std::mem::offset_of!(rte_kni_fifo, buffer) - 16usize]; +}; +impl Default for rte_kni_fifo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct rte_eth_link { + pub _bindgen_align: [u64; 0], + ///< ETH_SPEED_NUM_ + pub link_speed: u32, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_link"][::std::mem::size_of::() - 8usize]; + ["Alignment of rte_eth_link"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_link::link_speed", + ][::std::mem::offset_of!(rte_eth_link, link_speed) - 0usize]; +}; +impl rte_eth_link { + #[inline] + pub fn link_duplex(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } + } + #[inline] + pub fn set_link_duplex(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn link_duplex_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_link_duplex_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn link_autoneg(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } + } + #[inline] + pub fn set_link_autoneg(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn link_autoneg_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_link_autoneg_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn link_status(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } + } + #[inline] + pub fn set_link_status(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn link_status_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_link_status_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + link_duplex: u16, + link_autoneg: u16, + link_status: u16, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let link_duplex: u16 = unsafe { ::std::mem::transmute(link_duplex) }; + link_duplex as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let link_autoneg: u16 = unsafe { + ::std::mem::transmute(link_autoneg) + }; + link_autoneg as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let link_status: u16 = unsafe { ::std::mem::transmute(link_status) }; + link_status as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/layout_arp.rs b/bindgen-tests/tests/expectations/tests/layout_arp.rs new file mode 100644 index 0000000000..c94dc2ce24 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_arp.rs @@ -0,0 +1,96 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const ETHER_ADDR_LEN: u32 = 6; +pub const ARP_HRD_ETHER: u32 = 1; +pub const ARP_OP_REQUEST: u32 = 1; +pub const ARP_OP_REPLY: u32 = 2; +pub const ARP_OP_REVREQUEST: u32 = 3; +pub const ARP_OP_REVREPLY: u32 = 4; +pub const ARP_OP_INVREQUEST: u32 = 8; +pub const ARP_OP_INVREPLY: u32 = 9; +/** Ethernet address: + A universally administered address is uniquely assigned to a device by its + manufacturer. The first three octets (in transmission order) contain the + Organizationally Unique Identifier (OUI). The following three (MAC-48 and + EUI-48) octets are assigned by that organization with the only constraint + of uniqueness. + A locally administered address is assigned to a device by a network + administrator and does not contain OUIs. + See http://standards.ieee.org/regauth/groupmac/tutorial.html*/ +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ether_addr { + ///< Addr bytes in tx order + pub addr_bytes: [u8; 6usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ether_addr"][::std::mem::size_of::() - 6usize]; + ["Alignment of ether_addr"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ether_addr::addr_bytes", + ][::std::mem::offset_of!(ether_addr, addr_bytes) - 0usize]; +}; +/// ARP header IPv4 payload. +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct arp_ipv4 { + ///< sender hardware address + pub arp_sha: ether_addr, + ///< sender IP address + pub arp_sip: u32, + ///< target hardware address + pub arp_tha: ether_addr, + ///< target IP address + pub arp_tip: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of arp_ipv4"][::std::mem::size_of::() - 20usize]; + ["Alignment of arp_ipv4"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: arp_ipv4::arp_sha", + ][::std::mem::offset_of!(arp_ipv4, arp_sha) - 0usize]; + [ + "Offset of field: arp_ipv4::arp_sip", + ][::std::mem::offset_of!(arp_ipv4, arp_sip) - 6usize]; + [ + "Offset of field: arp_ipv4::arp_tha", + ][::std::mem::offset_of!(arp_ipv4, arp_tha) - 10usize]; + [ + "Offset of field: arp_ipv4::arp_tip", + ][::std::mem::offset_of!(arp_ipv4, arp_tip) - 16usize]; +}; +/// ARP header. +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct arp_hdr { + pub arp_hrd: u16, + pub arp_pro: u16, + pub arp_hln: u8, + pub arp_pln: u8, + pub arp_op: u16, + pub arp_data: arp_ipv4, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of arp_hdr"][::std::mem::size_of::() - 28usize]; + ["Alignment of arp_hdr"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: arp_hdr::arp_hrd", + ][::std::mem::offset_of!(arp_hdr, arp_hrd) - 0usize]; + [ + "Offset of field: arp_hdr::arp_pro", + ][::std::mem::offset_of!(arp_hdr, arp_pro) - 2usize]; + [ + "Offset of field: arp_hdr::arp_hln", + ][::std::mem::offset_of!(arp_hdr, arp_hln) - 4usize]; + [ + "Offset of field: arp_hdr::arp_pln", + ][::std::mem::offset_of!(arp_hdr, arp_pln) - 5usize]; + [ + "Offset of field: arp_hdr::arp_op", + ][::std::mem::offset_of!(arp_hdr, arp_op) - 6usize]; + [ + "Offset of field: arp_hdr::arp_data", + ][::std::mem::offset_of!(arp_hdr, arp_data) - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/layout_array.rs b/bindgen-tests/tests/expectations/tests/layout_array.rs new file mode 100644 index 0000000000..3afe1c2dd8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_array.rs @@ -0,0 +1,233 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +pub const RTE_CACHE_LINE_SIZE: u32 = 64; +pub const RTE_MEMPOOL_OPS_NAMESIZE: u32 = 32; +pub const RTE_MEMPOOL_MAX_OPS_IDX: u32 = 16; +pub const RTE_HEAP_NUM_FREELISTS: u32 = 13; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rte_mempool { + _unused: [u8; 0], +} +/** Prototype for implementation specific data provisioning function. + + The function should provide the implementation specific memory for + for use by the other mempool ops functions in a given mempool ops struct. + E.g. the default ops provides an instance of the rte_ring for this purpose. + it will most likely point to a different type of data structure, and + will be transparent to the application programmer. + This function should set mp->pool_data.*/ +pub type rte_mempool_alloc_t = ::std::option::Option< + unsafe extern "C" fn(mp: *mut rte_mempool) -> ::std::os::raw::c_int, +>; +/// Free the opaque private data pointed to by mp->pool_data pointer. +pub type rte_mempool_free_t = ::std::option::Option< + unsafe extern "C" fn(mp: *mut rte_mempool), +>; +/// Enqueue an object into the external pool. +pub type rte_mempool_enqueue_t = ::std::option::Option< + unsafe extern "C" fn( + mp: *mut rte_mempool, + obj_table: *const *mut ::std::os::raw::c_void, + n: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int, +>; +/// Dequeue an object from the external pool. +pub type rte_mempool_dequeue_t = ::std::option::Option< + unsafe extern "C" fn( + mp: *mut rte_mempool, + obj_table: *mut *mut ::std::os::raw::c_void, + n: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int, +>; +/// Return the number of available objects in the external pool. +pub type rte_mempool_get_count = ::std::option::Option< + unsafe extern "C" fn(mp: *const rte_mempool) -> ::std::os::raw::c_uint, +>; +/// Structure defining mempool operations structure +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mempool_ops { + ///< Name of mempool ops struct. + pub name: [::std::os::raw::c_char; 32usize], + ///< Allocate private data. + pub alloc: rte_mempool_alloc_t, + ///< Free the external pool. + pub free: rte_mempool_free_t, + ///< Enqueue an object. + pub enqueue: rte_mempool_enqueue_t, + ///< Dequeue an object. + pub dequeue: rte_mempool_dequeue_t, + ///< Get qty of available objs. + pub get_count: rte_mempool_get_count, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_mempool_ops"][::std::mem::size_of::() - 128usize]; + [ + "Alignment of rte_mempool_ops", + ][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: rte_mempool_ops::name", + ][::std::mem::offset_of!(rte_mempool_ops, name) - 0usize]; + [ + "Offset of field: rte_mempool_ops::alloc", + ][::std::mem::offset_of!(rte_mempool_ops, alloc) - 32usize]; + [ + "Offset of field: rte_mempool_ops::free", + ][::std::mem::offset_of!(rte_mempool_ops, free) - 40usize]; + [ + "Offset of field: rte_mempool_ops::enqueue", + ][::std::mem::offset_of!(rte_mempool_ops, enqueue) - 48usize]; + [ + "Offset of field: rte_mempool_ops::dequeue", + ][::std::mem::offset_of!(rte_mempool_ops, dequeue) - 56usize]; + [ + "Offset of field: rte_mempool_ops::get_count", + ][::std::mem::offset_of!(rte_mempool_ops, get_count) - 64usize]; +}; +impl Default for rte_mempool_ops { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// The rte_spinlock_t type. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_spinlock_t { + ///< lock status 0 = unlocked, 1 = locked + pub locked: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_spinlock_t"][::std::mem::size_of::() - 4usize]; + ["Alignment of rte_spinlock_t"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_spinlock_t::locked", + ][::std::mem::offset_of!(rte_spinlock_t, locked) - 0usize]; +}; +/** Structure storing the table of registered ops structs, each of which contain + the function pointers for the mempool ops functions. + Each process has its own storage for this ops struct array so that + the mempools can be shared across primary and secondary processes. + The indices used to access the array are valid across processes, whereas + any function pointers stored directly in the mempool struct would not be. + This results in us simply having "ops_index" in the mempool struct.*/ +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mempool_ops_table { + ///< Spinlock for add/delete. + pub sl: rte_spinlock_t, + ///< Number of used ops structs in the table. + pub num_ops: u32, + pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 56usize]>, + /// Storage for all possible ops structs. + pub ops: [rte_mempool_ops; 16usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mempool_ops_table", + ][::std::mem::size_of::() - 2112usize]; + [ + "Alignment of rte_mempool_ops_table", + ][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: rte_mempool_ops_table::sl", + ][::std::mem::offset_of!(rte_mempool_ops_table, sl) - 0usize]; + [ + "Offset of field: rte_mempool_ops_table::num_ops", + ][::std::mem::offset_of!(rte_mempool_ops_table, num_ops) - 4usize]; + [ + "Offset of field: rte_mempool_ops_table::ops", + ][::std::mem::offset_of!(rte_mempool_ops_table, ops) - 64usize]; +}; +impl Default for rte_mempool_ops_table { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// Structure to hold malloc heap +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct malloc_heap { + pub lock: rte_spinlock_t, + pub free_head: [malloc_heap__bindgen_ty_1; 13usize], + pub alloc_count: ::std::os::raw::c_uint, + pub total_size: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct malloc_heap__bindgen_ty_1 { + pub lh_first: *mut malloc_elem, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of malloc_heap__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of malloc_heap__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: malloc_heap__bindgen_ty_1::lh_first", + ][::std::mem::offset_of!(malloc_heap__bindgen_ty_1, lh_first) - 0usize]; +}; +impl Default for malloc_heap__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of malloc_heap"][::std::mem::size_of::() - 128usize]; + ["Alignment of malloc_heap"][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: malloc_heap::lock", + ][::std::mem::offset_of!(malloc_heap, lock) - 0usize]; + [ + "Offset of field: malloc_heap::free_head", + ][::std::mem::offset_of!(malloc_heap, free_head) - 8usize]; + [ + "Offset of field: malloc_heap::alloc_count", + ][::std::mem::offset_of!(malloc_heap, alloc_count) - 112usize]; + [ + "Offset of field: malloc_heap::total_size", + ][::std::mem::offset_of!(malloc_heap, total_size) - 120usize]; +}; +impl Default for malloc_heap { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct malloc_elem { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/layout_array_too_long.rs b/bindgen-tests/tests/expectations/tests/layout_array_too_long.rs new file mode 100644 index 0000000000..315663e0fc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_array_too_long.rs @@ -0,0 +1,163 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const RTE_CACHE_LINE_SIZE: u32 = 64; +pub const RTE_LIBRTE_IP_FRAG_MAX_FRAG: u32 = 4; +pub const IP_LAST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_LAST_FRAG_IDX; +pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX; +pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM; +pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + ///< index of last fragment + IP_LAST_FRAG_IDX = 0, + ///< index of first fragment + IP_FIRST_FRAG_IDX = 1, + ///< minimum number of fragments + IP_MIN_FRAG_NUM = 2, + IP_MAX_FRAG_NUM = 4, +} +/// @internal fragmented mbuf +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ip_frag { + ///< offset into the packet + pub ofs: u16, + ///< length of fragment + pub len: u16, + ///< fragment mbuf + pub mb: *mut rte_mbuf, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag"][::std::mem::size_of::() - 16usize]; + ["Alignment of ip_frag"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ip_frag::ofs"][::std::mem::offset_of!(ip_frag, ofs) - 0usize]; + ["Offset of field: ip_frag::len"][::std::mem::offset_of!(ip_frag, len) - 2usize]; + ["Offset of field: ip_frag::mb"][::std::mem::offset_of!(ip_frag, mb) - 8usize]; +}; +impl Default for ip_frag { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// @internal to uniquely indetify fragmented datagram. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ip_frag_key { + ///< src address, first 8 bytes used for IPv4 + pub src_dst: [u64; 4usize], + ///< dst address + pub id: u32, + ///< src/dst key length + pub key_len: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag_key"][::std::mem::size_of::() - 40usize]; + ["Alignment of ip_frag_key"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ip_frag_key::src_dst", + ][::std::mem::offset_of!(ip_frag_key, src_dst) - 0usize]; + [ + "Offset of field: ip_frag_key::id", + ][::std::mem::offset_of!(ip_frag_key, id) - 32usize]; + [ + "Offset of field: ip_frag_key::key_len", + ][::std::mem::offset_of!(ip_frag_key, key_len) - 36usize]; +}; +/** @internal Fragmented packet to reassemble. + First two entries in the frags[] array are for the last and first fragments.*/ +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ip_frag_pkt { + ///< LRU list + pub lru: ip_frag_pkt__bindgen_ty_1, + ///< fragmentation key + pub key: ip_frag_key, + ///< creation timestamp + pub start: u64, + ///< expected reassembled size + pub total_size: u32, + ///< size of fragments received + pub frag_size: u32, + ///< index of next entry to fill + pub last_idx: u32, + ///< fragments + pub frags: [ip_frag; 4usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ip_frag_pkt__bindgen_ty_1 { + pub tqe_next: *mut ip_frag_pkt, + pub tqe_prev: *mut *mut ip_frag_pkt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ip_frag_pkt__bindgen_ty_1", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of ip_frag_pkt__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ip_frag_pkt__bindgen_ty_1::tqe_next", + ][::std::mem::offset_of!(ip_frag_pkt__bindgen_ty_1, tqe_next) - 0usize]; + [ + "Offset of field: ip_frag_pkt__bindgen_ty_1::tqe_prev", + ][::std::mem::offset_of!(ip_frag_pkt__bindgen_ty_1, tqe_prev) - 8usize]; +}; +impl Default for ip_frag_pkt__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag_pkt"][::std::mem::size_of::() - 192usize]; + ["Alignment of ip_frag_pkt"][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: ip_frag_pkt::lru", + ][::std::mem::offset_of!(ip_frag_pkt, lru) - 0usize]; + [ + "Offset of field: ip_frag_pkt::key", + ][::std::mem::offset_of!(ip_frag_pkt, key) - 16usize]; + [ + "Offset of field: ip_frag_pkt::start", + ][::std::mem::offset_of!(ip_frag_pkt, start) - 56usize]; + [ + "Offset of field: ip_frag_pkt::total_size", + ][::std::mem::offset_of!(ip_frag_pkt, total_size) - 64usize]; + [ + "Offset of field: ip_frag_pkt::frag_size", + ][::std::mem::offset_of!(ip_frag_pkt, frag_size) - 68usize]; + [ + "Offset of field: ip_frag_pkt::last_idx", + ][::std::mem::offset_of!(ip_frag_pkt, last_idx) - 72usize]; + [ + "Offset of field: ip_frag_pkt::frags", + ][::std::mem::offset_of!(ip_frag_pkt, frags) - 80usize]; +}; +impl Default for ip_frag_pkt { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +///< fragment mbuf +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mbuf { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/layout_cmdline_token.rs b/bindgen-tests/tests/expectations/tests/layout_cmdline_token.rs new file mode 100644 index 0000000000..fb7b3bf584 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_cmdline_token.rs @@ -0,0 +1,173 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** Stores a pointer to the ops struct, and the offset: the place to + write the parsed result in the destination structure.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cmdline_token_hdr { + pub ops: *mut cmdline_token_ops, + pub offset: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cmdline_token_hdr"][::std::mem::size_of::() - 16usize]; + [ + "Alignment of cmdline_token_hdr", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: cmdline_token_hdr::ops", + ][::std::mem::offset_of!(cmdline_token_hdr, ops) - 0usize]; + [ + "Offset of field: cmdline_token_hdr::offset", + ][::std::mem::offset_of!(cmdline_token_hdr, offset) - 8usize]; +}; +impl Default for cmdline_token_hdr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/** Stores a pointer to the ops struct, and the offset: the place to + write the parsed result in the destination structure.*/ +pub type cmdline_parse_token_hdr_t = cmdline_token_hdr; +/** A token is defined by this structure. + + parse() takes the token as first argument, then the source buffer + starting at the token we want to parse. The 3rd arg is a pointer + where we store the parsed data (as binary). It returns the number of + parsed chars on success and a negative value on error. + + complete_get_nb() returns the number of possible values for this + token if completion is possible. If it is NULL or if it returns 0, + no completion is possible. + + complete_get_elt() copy in dstbuf (the size is specified in the + parameter) the i-th possible completion for this token. returns 0 + on success or and a negative value on error. + + get_help() fills the dstbuf with the help for the token. It returns + -1 on error and 0 on success.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct cmdline_token_ops { + /// parse(token ptr, buf, res pts, buf len) + pub parse: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut cmdline_parse_token_hdr_t, + arg2: *const ::std::os::raw::c_char, + arg3: *mut ::std::os::raw::c_void, + arg4: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int, + >, + /// return the num of possible choices for this token + pub complete_get_nb: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut cmdline_parse_token_hdr_t, + ) -> ::std::os::raw::c_int, + >, + /// return the elt x for this token (token, idx, dstbuf, size) + pub complete_get_elt: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut cmdline_parse_token_hdr_t, + arg2: ::std::os::raw::c_int, + arg3: *mut ::std::os::raw::c_char, + arg4: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int, + >, + /// get help for this token (token, dstbuf, size) + pub get_help: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut cmdline_parse_token_hdr_t, + arg2: *mut ::std::os::raw::c_char, + arg3: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int, + >, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cmdline_token_ops"][::std::mem::size_of::() - 32usize]; + [ + "Alignment of cmdline_token_ops", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: cmdline_token_ops::parse", + ][::std::mem::offset_of!(cmdline_token_ops, parse) - 0usize]; + [ + "Offset of field: cmdline_token_ops::complete_get_nb", + ][::std::mem::offset_of!(cmdline_token_ops, complete_get_nb) - 8usize]; + [ + "Offset of field: cmdline_token_ops::complete_get_elt", + ][::std::mem::offset_of!(cmdline_token_ops, complete_get_elt) - 16usize]; + [ + "Offset of field: cmdline_token_ops::get_help", + ][::std::mem::offset_of!(cmdline_token_ops, get_help) - 24usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum cmdline_numtype { + UINT8 = 0, + UINT16 = 1, + UINT32 = 2, + UINT64 = 3, + INT8 = 4, + INT16 = 5, + INT32 = 6, + INT64 = 7, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cmdline_token_num_data { + pub type_: cmdline_numtype, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of cmdline_token_num_data", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of cmdline_token_num_data", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: cmdline_token_num_data::type_", + ][::std::mem::offset_of!(cmdline_token_num_data, type_) - 0usize]; +}; +impl Default for cmdline_token_num_data { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cmdline_token_num { + pub hdr: cmdline_token_hdr, + pub num_data: cmdline_token_num_data, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cmdline_token_num"][::std::mem::size_of::() - 24usize]; + [ + "Alignment of cmdline_token_num", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: cmdline_token_num::hdr", + ][::std::mem::offset_of!(cmdline_token_num, hdr) - 0usize]; + [ + "Offset of field: cmdline_token_num::num_data", + ][::std::mem::offset_of!(cmdline_token_num, num_data) - 16usize]; +}; +impl Default for cmdline_token_num { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type cmdline_parse_token_num_t = cmdline_token_num; diff --git a/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs b/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs new file mode 100644 index 0000000000..7d975cd979 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs @@ -0,0 +1,1723 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +pub const ETH_MQ_RX_RSS_FLAG: u32 = 1; +pub const ETH_MQ_RX_DCB_FLAG: u32 = 2; +pub const ETH_MQ_RX_VMDQ_FLAG: u32 = 4; +pub const ETH_VMDQ_MAX_VLAN_FILTERS: u32 = 64; +pub const ETH_DCB_NUM_USER_PRIORITIES: u32 = 8; +pub const ETH_VMDQ_DCB_NUM_QUEUES: u32 = 128; +pub const ETH_DCB_NUM_QUEUES: u32 = 128; +pub const RTE_ETH_FDIR_MAX_FLEXLEN: u32 = 16; +pub const RTE_ETH_INSET_SIZE_MAX: u32 = 128; +pub const RTE_ETH_FLOW_UNKNOWN: u32 = 0; +pub const RTE_ETH_FLOW_RAW: u32 = 1; +pub const RTE_ETH_FLOW_IPV4: u32 = 2; +pub const RTE_ETH_FLOW_FRAG_IPV4: u32 = 3; +pub const RTE_ETH_FLOW_NONFRAG_IPV4_TCP: u32 = 4; +pub const RTE_ETH_FLOW_NONFRAG_IPV4_UDP: u32 = 5; +pub const RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: u32 = 6; +pub const RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: u32 = 7; +pub const RTE_ETH_FLOW_IPV6: u32 = 8; +pub const RTE_ETH_FLOW_FRAG_IPV6: u32 = 9; +pub const RTE_ETH_FLOW_NONFRAG_IPV6_TCP: u32 = 10; +pub const RTE_ETH_FLOW_NONFRAG_IPV6_UDP: u32 = 11; +pub const RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: u32 = 12; +pub const RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: u32 = 13; +pub const RTE_ETH_FLOW_L2_PAYLOAD: u32 = 14; +pub const RTE_ETH_FLOW_IPV6_EX: u32 = 15; +pub const RTE_ETH_FLOW_IPV6_TCP_EX: u32 = 16; +pub const RTE_ETH_FLOW_IPV6_UDP_EX: u32 = 17; +pub const RTE_ETH_FLOW_PORT: u32 = 18; +pub const RTE_ETH_FLOW_VXLAN: u32 = 19; +pub const RTE_ETH_FLOW_GENEVE: u32 = 20; +pub const RTE_ETH_FLOW_NVGRE: u32 = 21; +pub const RTE_ETH_FLOW_MAX: u32 = 22; +#[repr(u32)] +/** A set of values to identify what method is to be used to route + packets to multiple queues.*/ +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_eth_rx_mq_mode { + /// None of DCB,RSS or VMDQ mode + ETH_MQ_RX_NONE = 0, + /// For RX side, only RSS is on + ETH_MQ_RX_RSS = 1, + /// For RX side,only DCB is on. + ETH_MQ_RX_DCB = 2, + /// Both DCB and RSS enable + ETH_MQ_RX_DCB_RSS = 3, + /// Only VMDQ, no RSS nor DCB + ETH_MQ_RX_VMDQ_ONLY = 4, + /// RSS mode with VMDQ + ETH_MQ_RX_VMDQ_RSS = 5, + /// Use VMDQ+DCB to route traffic to queues + ETH_MQ_RX_VMDQ_DCB = 6, + /// Enable both VMDQ and DCB in VMDq + ETH_MQ_RX_VMDQ_DCB_RSS = 7, +} +/// A structure used to configure the RX features of an Ethernet port. +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_rxmode { + /// The multi-queue packet distribution mode to be used, e.g. RSS. + pub mq_mode: rte_eth_rx_mq_mode, + ///< Only used if jumbo_frame enabled. + pub max_rx_pkt_len: u32, + ///< hdr buf size (header_split enabled). + pub split_hdr_size: u16, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_rxmode"][::std::mem::size_of::() - 12usize]; + ["Alignment of rte_eth_rxmode"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_rxmode::mq_mode", + ][::std::mem::offset_of!(rte_eth_rxmode, mq_mode) - 0usize]; + [ + "Offset of field: rte_eth_rxmode::max_rx_pkt_len", + ][::std::mem::offset_of!(rte_eth_rxmode, max_rx_pkt_len) - 4usize]; + [ + "Offset of field: rte_eth_rxmode::split_hdr_size", + ][::std::mem::offset_of!(rte_eth_rxmode, split_hdr_size) - 8usize]; +}; +impl Default for rte_eth_rxmode { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl rte_eth_rxmode { + #[inline] + pub fn header_split(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } + } + #[inline] + pub fn set_header_split(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn header_split_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_header_split_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_ip_checksum(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } + } + #[inline] + pub fn set_hw_ip_checksum(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_ip_checksum_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_hw_ip_checksum_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_vlan_filter(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } + } + #[inline] + pub fn set_hw_vlan_filter(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_filter_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_filter_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_vlan_strip(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } + } + #[inline] + pub fn set_hw_vlan_strip(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_strip_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 3usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_strip_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 3usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_vlan_extend(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } + } + #[inline] + pub fn set_hw_vlan_extend(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_extend_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_extend_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn jumbo_frame(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } + } + #[inline] + pub fn set_jumbo_frame(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn jumbo_frame_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 5usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_jumbo_frame_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 5usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_strip_crc(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) } + } + #[inline] + pub fn set_hw_strip_crc(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_strip_crc_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 6usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_hw_strip_crc_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 6usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn enable_scatter(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) } + } + #[inline] + pub fn set_enable_scatter(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn enable_scatter_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_enable_scatter_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn enable_lro(&self) -> u16 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } + } + #[inline] + pub fn set_enable_lro(&mut self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn enable_lro_raw(this: *const Self) -> u16 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_enable_lro_raw(this: *mut Self, val: u16) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + header_split: u16, + hw_ip_checksum: u16, + hw_vlan_filter: u16, + hw_vlan_strip: u16, + hw_vlan_extend: u16, + jumbo_frame: u16, + hw_strip_crc: u16, + enable_scatter: u16, + enable_lro: u16, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let header_split: u16 = unsafe { + ::std::mem::transmute(header_split) + }; + header_split as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let hw_ip_checksum: u16 = unsafe { + ::std::mem::transmute(hw_ip_checksum) + }; + hw_ip_checksum as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let hw_vlan_filter: u16 = unsafe { + ::std::mem::transmute(hw_vlan_filter) + }; + hw_vlan_filter as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 1u8, + { + let hw_vlan_strip: u16 = unsafe { + ::std::mem::transmute(hw_vlan_strip) + }; + hw_vlan_strip as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 1u8, + { + let hw_vlan_extend: u16 = unsafe { + ::std::mem::transmute(hw_vlan_extend) + }; + hw_vlan_extend as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 5usize, + 1u8, + { + let jumbo_frame: u16 = unsafe { ::std::mem::transmute(jumbo_frame) }; + jumbo_frame as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 1u8, + { + let hw_strip_crc: u16 = unsafe { + ::std::mem::transmute(hw_strip_crc) + }; + hw_strip_crc as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 1u8, + { + let enable_scatter: u16 = unsafe { + ::std::mem::transmute(enable_scatter) + }; + enable_scatter as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 1u8, + { + let enable_lro: u16 = unsafe { ::std::mem::transmute(enable_lro) }; + enable_lro as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(u32)] +/** A set of values to identify what method is to be used to transmit + packets using multi-TCs.*/ +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_eth_tx_mq_mode { + ///< It is in neither DCB nor VT mode. + ETH_MQ_TX_NONE = 0, + ///< For TX side,only DCB is on. + ETH_MQ_TX_DCB = 1, + ///< For TX side,both DCB and VT is on. + ETH_MQ_TX_VMDQ_DCB = 2, + ///< Only VT on, no DCB + ETH_MQ_TX_VMDQ_ONLY = 3, +} +/// A structure used to configure the TX features of an Ethernet port. +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_txmode { + ///< TX multi-queues mode. + pub mq_mode: rte_eth_tx_mq_mode, + pub pvid: u16, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_txmode"][::std::mem::size_of::() - 8usize]; + ["Alignment of rte_eth_txmode"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_txmode::mq_mode", + ][::std::mem::offset_of!(rte_eth_txmode, mq_mode) - 0usize]; + [ + "Offset of field: rte_eth_txmode::pvid", + ][::std::mem::offset_of!(rte_eth_txmode, pvid) - 4usize]; +}; +impl Default for rte_eth_txmode { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl rte_eth_txmode { + #[inline] + pub fn hw_vlan_reject_tagged(&self) -> u8 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_hw_vlan_reject_tagged(&mut self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_reject_tagged_raw(this: *const Self) -> u8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_reject_tagged_raw(this: *mut Self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_vlan_reject_untagged(&self) -> u8 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub fn set_hw_vlan_reject_untagged(&mut self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_reject_untagged_raw(this: *const Self) -> u8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_reject_untagged_raw(this: *mut Self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn hw_vlan_insert_pvid(&self) -> u8 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } + } + #[inline] + pub fn set_hw_vlan_insert_pvid(&mut self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn hw_vlan_insert_pvid_raw(this: *const Self) -> u8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_hw_vlan_insert_pvid_raw(this: *mut Self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + hw_vlan_reject_tagged: u8, + hw_vlan_reject_untagged: u8, + hw_vlan_insert_pvid: u8, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let hw_vlan_reject_tagged: u8 = unsafe { + ::std::mem::transmute(hw_vlan_reject_tagged) + }; + hw_vlan_reject_tagged as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let hw_vlan_reject_untagged: u8 = unsafe { + ::std::mem::transmute(hw_vlan_reject_untagged) + }; + hw_vlan_reject_untagged as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let hw_vlan_insert_pvid: u8 = unsafe { + ::std::mem::transmute(hw_vlan_insert_pvid) + }; + hw_vlan_insert_pvid as u64 + }, + ); + __bindgen_bitfield_unit + } +} +/** A structure used to configure the Receive Side Scaling (RSS) feature + of an Ethernet port. + If not NULL, the *rss_key* pointer of the *rss_conf* structure points + to an array holding the RSS key to use for hashing specific header + fields of received packets. The length of this array should be indicated + by *rss_key_len* below. Otherwise, a default random hash key is used by + the device driver. + + The *rss_key_len* field of the *rss_conf* structure indicates the length + in bytes of the array pointed by *rss_key*. To be compatible, this length + will be checked in i40e only. Others assume 40 bytes to be used as before. + + The *rss_hf* field of the *rss_conf* structure indicates the different + types of IPv4/IPv6 packets to which the RSS hashing must be applied. + Supplying an *rss_hf* equal to zero disables the RSS feature.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_rss_conf { + ///< If not NULL, 40-byte hash key. + pub rss_key: *mut u8, + ///< hash key length in bytes. + pub rss_key_len: u8, + ///< Hash functions to apply - see below. + pub rss_hf: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_rss_conf"][::std::mem::size_of::() - 24usize]; + [ + "Alignment of rte_eth_rss_conf", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_rss_conf::rss_key", + ][::std::mem::offset_of!(rte_eth_rss_conf, rss_key) - 0usize]; + [ + "Offset of field: rte_eth_rss_conf::rss_key_len", + ][::std::mem::offset_of!(rte_eth_rss_conf, rss_key_len) - 8usize]; + [ + "Offset of field: rte_eth_rss_conf::rss_hf", + ][::std::mem::offset_of!(rte_eth_rss_conf, rss_hf) - 16usize]; +}; +impl Default for rte_eth_rss_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(u32)] +/** This enum indicates the possible number of traffic classes + in DCB configratioins*/ +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_eth_nb_tcs { + ///< 4 TCs with DCB. + ETH_4_TCS = 4, + ///< 8 TCs with DCB. + ETH_8_TCS = 8, +} +#[repr(u32)] +/** This enum indicates the possible number of queue pools + in VMDQ configurations.*/ +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_eth_nb_pools { + ///< 8 VMDq pools. + ETH_8_POOLS = 8, + ///< 16 VMDq pools. + ETH_16_POOLS = 16, + ///< 32 VMDq pools. + ETH_32_POOLS = 32, + ///< 64 VMDq pools. + ETH_64_POOLS = 64, +} +/** A structure used to configure the VMDQ+DCB feature + of an Ethernet port. + + Using this feature, packets are routed to a pool of queues, based + on the vlan ID in the vlan tag, and then to a specific queue within + that pool, using the user priority vlan tag field. + + A default pool may be used, if desired, to route all traffic which + does not match the vlan filter rules.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_dcb_conf { + ///< With DCB, 16 or 32 pools + pub nb_queue_pools: rte_eth_nb_pools, + ///< If non-zero, use a default pool + pub enable_default_pool: u8, + ///< The default pool, if applicable + pub default_pool: u8, + ///< We can have up to 64 filters/mappings + pub nb_pool_maps: u8, + ///< VMDq vlan pool maps. + pub pool_map: [rte_eth_vmdq_dcb_conf__bindgen_ty_1; 64usize], + pub dcb_tc: [u8; 8usize], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_dcb_conf__bindgen_ty_1 { + ///< The vlan ID of the received frame + pub vlan_id: u16, + ///< Bitmask of pools for packet rx + pub pools: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_dcb_conf__bindgen_ty_1", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of rte_eth_vmdq_dcb_conf__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf__bindgen_ty_1::vlan_id", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf__bindgen_ty_1, vlan_id) - 0usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf__bindgen_ty_1::pools", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf__bindgen_ty_1, pools) - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_dcb_conf", + ][::std::mem::size_of::() - 1040usize]; + [ + "Alignment of rte_eth_vmdq_dcb_conf", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::nb_queue_pools", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, nb_queue_pools) - 0usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::enable_default_pool", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, enable_default_pool) - 4usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::default_pool", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, default_pool) - 5usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::nb_pool_maps", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, nb_pool_maps) - 6usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::pool_map", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, pool_map) - 8usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_conf::dcb_tc", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_conf, dcb_tc) - 1032usize]; +}; +impl Default for rte_eth_vmdq_dcb_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_dcb_rx_conf { + ///< Possible DCB TCs, 4 or 8 TCs + pub nb_tcs: rte_eth_nb_tcs, + /// Traffic class each UP mapped to. + pub dcb_tc: [u8; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_dcb_rx_conf", + ][::std::mem::size_of::() - 12usize]; + [ + "Alignment of rte_eth_dcb_rx_conf", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_dcb_rx_conf::nb_tcs", + ][::std::mem::offset_of!(rte_eth_dcb_rx_conf, nb_tcs) - 0usize]; + [ + "Offset of field: rte_eth_dcb_rx_conf::dcb_tc", + ][::std::mem::offset_of!(rte_eth_dcb_rx_conf, dcb_tc) - 4usize]; +}; +impl Default for rte_eth_dcb_rx_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_dcb_tx_conf { + ///< With DCB, 16 or 32 pools. + pub nb_queue_pools: rte_eth_nb_pools, + /// Traffic class each UP mapped to. + pub dcb_tc: [u8; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_dcb_tx_conf", + ][::std::mem::size_of::() - 12usize]; + [ + "Alignment of rte_eth_vmdq_dcb_tx_conf", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_tx_conf::nb_queue_pools", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_tx_conf, nb_queue_pools) - 0usize]; + [ + "Offset of field: rte_eth_vmdq_dcb_tx_conf::dcb_tc", + ][::std::mem::offset_of!(rte_eth_vmdq_dcb_tx_conf, dcb_tc) - 4usize]; +}; +impl Default for rte_eth_vmdq_dcb_tx_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_dcb_tx_conf { + ///< Possible DCB TCs, 4 or 8 TCs. + pub nb_tcs: rte_eth_nb_tcs, + /// Traffic class each UP mapped to. + pub dcb_tc: [u8; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_dcb_tx_conf", + ][::std::mem::size_of::() - 12usize]; + [ + "Alignment of rte_eth_dcb_tx_conf", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_dcb_tx_conf::nb_tcs", + ][::std::mem::offset_of!(rte_eth_dcb_tx_conf, nb_tcs) - 0usize]; + [ + "Offset of field: rte_eth_dcb_tx_conf::dcb_tc", + ][::std::mem::offset_of!(rte_eth_dcb_tx_conf, dcb_tc) - 4usize]; +}; +impl Default for rte_eth_dcb_tx_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_tx_conf { + ///< VMDq mode, 64 pools. + pub nb_queue_pools: rte_eth_nb_pools, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_tx_conf", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_eth_vmdq_tx_conf", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_vmdq_tx_conf::nb_queue_pools", + ][::std::mem::offset_of!(rte_eth_vmdq_tx_conf, nb_queue_pools) - 0usize]; +}; +impl Default for rte_eth_vmdq_tx_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_rx_conf { + ///< VMDq only mode, 8 or 64 pools + pub nb_queue_pools: rte_eth_nb_pools, + ///< If non-zero, use a default pool + pub enable_default_pool: u8, + ///< The default pool, if applicable + pub default_pool: u8, + ///< Enable VT loop back + pub enable_loop_back: u8, + ///< We can have up to 64 filters/mappings + pub nb_pool_maps: u8, + ///< Flags from ETH_VMDQ_ACCEPT_* + pub rx_mode: u32, + ///< VMDq vlan pool maps. + pub pool_map: [rte_eth_vmdq_rx_conf__bindgen_ty_1; 64usize], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_vmdq_rx_conf__bindgen_ty_1 { + ///< The vlan ID of the received frame + pub vlan_id: u16, + ///< Bitmask of pools for packet rx + pub pools: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_rx_conf__bindgen_ty_1", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of rte_eth_vmdq_rx_conf__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf__bindgen_ty_1::vlan_id", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf__bindgen_ty_1, vlan_id) - 0usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf__bindgen_ty_1::pools", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf__bindgen_ty_1, pools) - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_vmdq_rx_conf", + ][::std::mem::size_of::() - 1040usize]; + [ + "Alignment of rte_eth_vmdq_rx_conf", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::nb_queue_pools", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, nb_queue_pools) - 0usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::enable_default_pool", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, enable_default_pool) - 4usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::default_pool", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, default_pool) - 5usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::enable_loop_back", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, enable_loop_back) - 6usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::nb_pool_maps", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, nb_pool_maps) - 7usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::rx_mode", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, rx_mode) - 8usize]; + [ + "Offset of field: rte_eth_vmdq_rx_conf::pool_map", + ][::std::mem::offset_of!(rte_eth_vmdq_rx_conf, pool_map) - 16usize]; +}; +impl Default for rte_eth_vmdq_rx_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(u32)] +/// Flow Director setting modes: none, signature or perfect. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_fdir_mode { + ///< Disable FDIR support. + RTE_FDIR_MODE_NONE = 0, + ///< Enable FDIR signature filter mode. + RTE_FDIR_MODE_SIGNATURE = 1, + ///< Enable FDIR perfect filter mode. + RTE_FDIR_MODE_PERFECT = 2, + ///< Enable FDIR filter mode - MAC VLAN. + RTE_FDIR_MODE_PERFECT_MAC_VLAN = 3, + ///< Enable FDIR filter mode - tunnel. + RTE_FDIR_MODE_PERFECT_TUNNEL = 4, +} +#[repr(u32)] +/** Memory space that can be configured to store Flow Director filters + in the board memory.*/ +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_fdir_pballoc_type { + ///< 64k. + RTE_FDIR_PBALLOC_64K = 0, + ///< 128k. + RTE_FDIR_PBALLOC_128K = 1, + ///< 256k. + RTE_FDIR_PBALLOC_256K = 2, +} +#[repr(u32)] +/// Select report mode of FDIR hash information in RX descriptors. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_fdir_status_mode { + ///< Never report FDIR hash. + RTE_FDIR_NO_REPORT_STATUS = 0, + ///< Only report FDIR hash for matching pkts. + RTE_FDIR_REPORT_STATUS = 1, + ///< Always report FDIR hash. + RTE_FDIR_REPORT_STATUS_ALWAYS = 2, +} +/// A structure used to define the input for IPV4 flow +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_ipv4_flow { + ///< IPv4 source address in big endian. + pub src_ip: u32, + ///< IPv4 destination address in big endian. + pub dst_ip: u32, + ///< Type of service to match. + pub tos: u8, + ///< Time to live to match. + pub ttl: u8, + ///< Protocol, next header in big endian. + pub proto: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_ipv4_flow"][::std::mem::size_of::() - 12usize]; + [ + "Alignment of rte_eth_ipv4_flow", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_ipv4_flow::src_ip", + ][::std::mem::offset_of!(rte_eth_ipv4_flow, src_ip) - 0usize]; + [ + "Offset of field: rte_eth_ipv4_flow::dst_ip", + ][::std::mem::offset_of!(rte_eth_ipv4_flow, dst_ip) - 4usize]; + [ + "Offset of field: rte_eth_ipv4_flow::tos", + ][::std::mem::offset_of!(rte_eth_ipv4_flow, tos) - 8usize]; + [ + "Offset of field: rte_eth_ipv4_flow::ttl", + ][::std::mem::offset_of!(rte_eth_ipv4_flow, ttl) - 9usize]; + [ + "Offset of field: rte_eth_ipv4_flow::proto", + ][::std::mem::offset_of!(rte_eth_ipv4_flow, proto) - 10usize]; +}; +/// A structure used to define the input for IPV6 flow +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_ipv6_flow { + ///< IPv6 source address in big endian. + pub src_ip: [u32; 4usize], + ///< IPv6 destination address in big endian. + pub dst_ip: [u32; 4usize], + ///< Traffic class to match. + pub tc: u8, + ///< Protocol, next header to match. + pub proto: u8, + ///< Hop limits to match. + pub hop_limits: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_ipv6_flow"][::std::mem::size_of::() - 36usize]; + [ + "Alignment of rte_eth_ipv6_flow", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_ipv6_flow::src_ip", + ][::std::mem::offset_of!(rte_eth_ipv6_flow, src_ip) - 0usize]; + [ + "Offset of field: rte_eth_ipv6_flow::dst_ip", + ][::std::mem::offset_of!(rte_eth_ipv6_flow, dst_ip) - 16usize]; + [ + "Offset of field: rte_eth_ipv6_flow::tc", + ][::std::mem::offset_of!(rte_eth_ipv6_flow, tc) - 32usize]; + [ + "Offset of field: rte_eth_ipv6_flow::proto", + ][::std::mem::offset_of!(rte_eth_ipv6_flow, proto) - 33usize]; + [ + "Offset of field: rte_eth_ipv6_flow::hop_limits", + ][::std::mem::offset_of!(rte_eth_ipv6_flow, hop_limits) - 34usize]; +}; +/** A structure used to configure FDIR masks that are used by the device + to match the various fields of RX packet headers.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_fdir_masks { + ///< Bit mask for vlan_tci in big endian + pub vlan_tci_mask: u16, + /// Bit mask for ipv4 flow in big endian. + pub ipv4_mask: rte_eth_ipv4_flow, + /// Bit maks for ipv6 flow in big endian. + pub ipv6_mask: rte_eth_ipv6_flow, + /// Bit mask for L4 source port in big endian. + pub src_port_mask: u16, + /// Bit mask for L4 destination port in big endian. + pub dst_port_mask: u16, + /** 6 bit mask for proper 6 bytes of Mac address, bit 0 matches the +first byte on the wire*/ + pub mac_addr_byte_mask: u8, + /// Bit mask for tunnel ID in big endian. + pub tunnel_id_mask: u32, + /**< 1 - Match tunnel type, +0 - Ignore tunnel type.*/ + pub tunnel_type_mask: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_fdir_masks", + ][::std::mem::size_of::() - 68usize]; + [ + "Alignment of rte_eth_fdir_masks", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_fdir_masks::vlan_tci_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, vlan_tci_mask) - 0usize]; + [ + "Offset of field: rte_eth_fdir_masks::ipv4_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, ipv4_mask) - 4usize]; + [ + "Offset of field: rte_eth_fdir_masks::ipv6_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, ipv6_mask) - 16usize]; + [ + "Offset of field: rte_eth_fdir_masks::src_port_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, src_port_mask) - 52usize]; + [ + "Offset of field: rte_eth_fdir_masks::dst_port_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, dst_port_mask) - 54usize]; + [ + "Offset of field: rte_eth_fdir_masks::mac_addr_byte_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, mac_addr_byte_mask) - 56usize]; + [ + "Offset of field: rte_eth_fdir_masks::tunnel_id_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, tunnel_id_mask) - 60usize]; + [ + "Offset of field: rte_eth_fdir_masks::tunnel_type_mask", + ][::std::mem::offset_of!(rte_eth_fdir_masks, tunnel_type_mask) - 64usize]; +}; +#[repr(u32)] +/// Payload type +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum rte_eth_payload_type { + RTE_ETH_PAYLOAD_UNKNOWN = 0, + RTE_ETH_RAW_PAYLOAD = 1, + RTE_ETH_L2_PAYLOAD = 2, + RTE_ETH_L3_PAYLOAD = 3, + RTE_ETH_L4_PAYLOAD = 4, + RTE_ETH_PAYLOAD_MAX = 8, +} +/** A structure used to select bytes extracted from the protocol layers to + flexible payload for filter*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_flex_payload_cfg { + ///< Payload type + pub type_: rte_eth_payload_type, + pub src_offset: [u16; 16usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_flex_payload_cfg", + ][::std::mem::size_of::() - 36usize]; + [ + "Alignment of rte_eth_flex_payload_cfg", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_flex_payload_cfg::type_", + ][::std::mem::offset_of!(rte_eth_flex_payload_cfg, type_) - 0usize]; + [ + "Offset of field: rte_eth_flex_payload_cfg::src_offset", + ][::std::mem::offset_of!(rte_eth_flex_payload_cfg, src_offset) - 4usize]; +}; +impl Default for rte_eth_flex_payload_cfg { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/** A structure used to define FDIR masks for flexible payload + for each flow type*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_fdir_flex_mask { + pub flow_type: u16, + pub mask: [u8; 16usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_fdir_flex_mask", + ][::std::mem::size_of::() - 18usize]; + [ + "Alignment of rte_eth_fdir_flex_mask", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_eth_fdir_flex_mask::flow_type", + ][::std::mem::offset_of!(rte_eth_fdir_flex_mask, flow_type) - 0usize]; + [ + "Offset of field: rte_eth_fdir_flex_mask::mask", + ][::std::mem::offset_of!(rte_eth_fdir_flex_mask, mask) - 2usize]; +}; +/** A structure used to define all flexible payload related setting + include flex payload and flex mask*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_fdir_flex_conf { + ///< The number of following payload cfg + pub nb_payloads: u16, + ///< The number of following mask + pub nb_flexmasks: u16, + pub flex_set: [rte_eth_flex_payload_cfg; 8usize], + pub flex_mask: [rte_eth_fdir_flex_mask; 22usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_fdir_flex_conf", + ][::std::mem::size_of::() - 688usize]; + [ + "Alignment of rte_eth_fdir_flex_conf", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_fdir_flex_conf::nb_payloads", + ][::std::mem::offset_of!(rte_eth_fdir_flex_conf, nb_payloads) - 0usize]; + [ + "Offset of field: rte_eth_fdir_flex_conf::nb_flexmasks", + ][::std::mem::offset_of!(rte_eth_fdir_flex_conf, nb_flexmasks) - 2usize]; + [ + "Offset of field: rte_eth_fdir_flex_conf::flex_set", + ][::std::mem::offset_of!(rte_eth_fdir_flex_conf, flex_set) - 4usize]; + [ + "Offset of field: rte_eth_fdir_flex_conf::flex_mask", + ][::std::mem::offset_of!(rte_eth_fdir_flex_conf, flex_mask) - 292usize]; +}; +impl Default for rte_eth_fdir_flex_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/** A structure used to configure the Flow Director (FDIR) feature + of an Ethernet port. + + If mode is RTE_FDIR_DISABLE, the pballoc value is ignored.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_fdir_conf { + ///< Flow Director mode. + pub mode: rte_fdir_mode, + ///< Space for FDIR filters. + pub pballoc: rte_fdir_pballoc_type, + ///< How to report FDIR hash. + pub status: rte_fdir_status_mode, + /// RX queue of packets matching a "drop" filter in perfect mode. + pub drop_queue: u8, + pub mask: rte_eth_fdir_masks, + pub flex_conf: rte_eth_fdir_flex_conf, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_fdir_conf"][::std::mem::size_of::() - 772usize]; + ["Alignment of rte_fdir_conf"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_fdir_conf::mode", + ][::std::mem::offset_of!(rte_fdir_conf, mode) - 0usize]; + [ + "Offset of field: rte_fdir_conf::pballoc", + ][::std::mem::offset_of!(rte_fdir_conf, pballoc) - 4usize]; + [ + "Offset of field: rte_fdir_conf::status", + ][::std::mem::offset_of!(rte_fdir_conf, status) - 8usize]; + [ + "Offset of field: rte_fdir_conf::drop_queue", + ][::std::mem::offset_of!(rte_fdir_conf, drop_queue) - 12usize]; + [ + "Offset of field: rte_fdir_conf::mask", + ][::std::mem::offset_of!(rte_fdir_conf, mask) - 16usize]; + [ + "Offset of field: rte_fdir_conf::flex_conf", + ][::std::mem::offset_of!(rte_fdir_conf, flex_conf) - 84usize]; +}; +impl Default for rte_fdir_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// A structure used to enable/disable specific device interrupts. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_intr_conf { + /// enable/disable lsc interrupt. 0 (default) - disable, 1 enable + pub lsc: u16, + /// enable/disable rxq interrupt. 0 (default) - disable, 1 enable + pub rxq: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_intr_conf"][::std::mem::size_of::() - 4usize]; + ["Alignment of rte_intr_conf"][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_intr_conf::lsc", + ][::std::mem::offset_of!(rte_intr_conf, lsc) - 0usize]; + [ + "Offset of field: rte_intr_conf::rxq", + ][::std::mem::offset_of!(rte_intr_conf, rxq) - 2usize]; +}; +/** A structure used to configure an Ethernet port. + Depending upon the RX multi-queue mode, extra advanced + configuration settings may be needed.*/ +#[repr(C)] +#[derive(Copy, Clone)] +pub struct rte_eth_conf { + /**< bitmap of ETH_LINK_SPEED_XXX of speeds to be +used. ETH_LINK_SPEED_FIXED disables link +autonegotiation, and a unique speed shall be +set. Otherwise, the bitmap defines the set of +speeds to be advertised. If the special value +ETH_LINK_SPEED_AUTONEG (0) is used, all speeds +supported are advertised.*/ + pub link_speeds: u32, + ///< Port RX configuration. + pub rxmode: rte_eth_rxmode, + ///< Port TX configuration. + pub txmode: rte_eth_txmode, + /**< Loopback operation mode. By default the value +is 0, meaning the loopback mode is disabled. +Read the datasheet of given ethernet controller +for details. The possible values of this field +are defined in implementation of each driver.*/ + pub lpbk_mode: u32, + ///< Port RX filtering configuration (union). + pub rx_adv_conf: rte_eth_conf__bindgen_ty_1, + ///< Port TX DCB configuration (union). + pub tx_adv_conf: rte_eth_conf__bindgen_ty_2, + /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC +is needed,and the variable must be set ETH_DCB_PFC_SUPPORT.*/ + pub dcb_capability_en: u32, + ///< FDIR configuration. + pub fdir_conf: rte_fdir_conf, + ///< Interrupt mode configuration. + pub intr_conf: rte_intr_conf, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_eth_conf__bindgen_ty_1 { + ///< Port RSS configuration + pub rss_conf: rte_eth_rss_conf, + pub vmdq_dcb_conf: rte_eth_vmdq_dcb_conf, + pub dcb_rx_conf: rte_eth_dcb_rx_conf, + pub vmdq_rx_conf: rte_eth_vmdq_rx_conf, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_conf__bindgen_ty_1", + ][::std::mem::size_of::() - 2120usize]; + [ + "Alignment of rte_eth_conf__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_1::rss_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_1, rss_conf) - 0usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_1::vmdq_dcb_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_1, vmdq_dcb_conf) - 24usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_1::dcb_rx_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_1, dcb_rx_conf) - 1064usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_1::vmdq_rx_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_1, vmdq_rx_conf) - 1080usize]; +}; +impl Default for rte_eth_conf__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_eth_conf__bindgen_ty_2 { + pub vmdq_dcb_tx_conf: rte_eth_vmdq_dcb_tx_conf, + pub dcb_tx_conf: rte_eth_dcb_tx_conf, + pub vmdq_tx_conf: rte_eth_vmdq_tx_conf, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_eth_conf__bindgen_ty_2", + ][::std::mem::size_of::() - 12usize]; + [ + "Alignment of rte_eth_conf__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_2::vmdq_dcb_tx_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_2, vmdq_dcb_tx_conf) - 0usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_2::dcb_tx_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_2, dcb_tx_conf) - 0usize]; + [ + "Offset of field: rte_eth_conf__bindgen_ty_2::vmdq_tx_conf", + ][::std::mem::offset_of!(rte_eth_conf__bindgen_ty_2, vmdq_tx_conf) - 0usize]; +}; +impl Default for rte_eth_conf__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_eth_conf"][::std::mem::size_of::() - 2944usize]; + ["Alignment of rte_eth_conf"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_eth_conf::link_speeds", + ][::std::mem::offset_of!(rte_eth_conf, link_speeds) - 0usize]; + [ + "Offset of field: rte_eth_conf::rxmode", + ][::std::mem::offset_of!(rte_eth_conf, rxmode) - 4usize]; + [ + "Offset of field: rte_eth_conf::txmode", + ][::std::mem::offset_of!(rte_eth_conf, txmode) - 16usize]; + [ + "Offset of field: rte_eth_conf::lpbk_mode", + ][::std::mem::offset_of!(rte_eth_conf, lpbk_mode) - 24usize]; + [ + "Offset of field: rte_eth_conf::rx_adv_conf", + ][::std::mem::offset_of!(rte_eth_conf, rx_adv_conf) - 32usize]; + [ + "Offset of field: rte_eth_conf::tx_adv_conf", + ][::std::mem::offset_of!(rte_eth_conf, tx_adv_conf) - 2152usize]; + [ + "Offset of field: rte_eth_conf::dcb_capability_en", + ][::std::mem::offset_of!(rte_eth_conf, dcb_capability_en) - 2164usize]; + [ + "Offset of field: rte_eth_conf::fdir_conf", + ][::std::mem::offset_of!(rte_eth_conf, fdir_conf) - 2168usize]; + [ + "Offset of field: rte_eth_conf::intr_conf", + ][::std::mem::offset_of!(rte_eth_conf, intr_conf) - 2940usize]; +}; +impl Default for rte_eth_conf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/layout_kni_mbuf.rs b/bindgen-tests/tests/expectations/tests/layout_kni_mbuf.rs new file mode 100644 index 0000000000..38f49fb4f0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_kni_mbuf.rs @@ -0,0 +1,84 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const RTE_CACHE_LINE_MIN_SIZE: u32 = 64; +pub const RTE_CACHE_LINE_SIZE: u32 = 64; +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone)] +pub struct rte_kni_mbuf { + pub buf_addr: *mut ::std::os::raw::c_void, + pub buf_physaddr: u64, + pub pad0: [::std::os::raw::c_char; 2usize], + ///< Start address of data in segment buffer. + pub data_off: u16, + pub pad1: [::std::os::raw::c_char; 2usize], + ///< Number of segments. + pub nb_segs: u8, + pub pad4: [::std::os::raw::c_char; 1usize], + ///< Offload features. + pub ol_flags: u64, + pub pad2: [::std::os::raw::c_char; 4usize], + ///< Total pkt len: sum of all segment data_len. + pub pkt_len: u32, + ///< Amount of data in segment buffer. + pub data_len: u16, + pub __bindgen_padding_0: [u8; 22usize], + pub pad3: [::std::os::raw::c_char; 8usize], + pub pool: *mut ::std::os::raw::c_void, + pub next: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_kni_mbuf"][::std::mem::size_of::() - 128usize]; + ["Alignment of rte_kni_mbuf"][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: rte_kni_mbuf::buf_addr", + ][::std::mem::offset_of!(rte_kni_mbuf, buf_addr) - 0usize]; + [ + "Offset of field: rte_kni_mbuf::buf_physaddr", + ][::std::mem::offset_of!(rte_kni_mbuf, buf_physaddr) - 8usize]; + [ + "Offset of field: rte_kni_mbuf::pad0", + ][::std::mem::offset_of!(rte_kni_mbuf, pad0) - 16usize]; + [ + "Offset of field: rte_kni_mbuf::data_off", + ][::std::mem::offset_of!(rte_kni_mbuf, data_off) - 18usize]; + [ + "Offset of field: rte_kni_mbuf::pad1", + ][::std::mem::offset_of!(rte_kni_mbuf, pad1) - 20usize]; + [ + "Offset of field: rte_kni_mbuf::nb_segs", + ][::std::mem::offset_of!(rte_kni_mbuf, nb_segs) - 22usize]; + [ + "Offset of field: rte_kni_mbuf::pad4", + ][::std::mem::offset_of!(rte_kni_mbuf, pad4) - 23usize]; + [ + "Offset of field: rte_kni_mbuf::ol_flags", + ][::std::mem::offset_of!(rte_kni_mbuf, ol_flags) - 24usize]; + [ + "Offset of field: rte_kni_mbuf::pad2", + ][::std::mem::offset_of!(rte_kni_mbuf, pad2) - 32usize]; + [ + "Offset of field: rte_kni_mbuf::pkt_len", + ][::std::mem::offset_of!(rte_kni_mbuf, pkt_len) - 36usize]; + [ + "Offset of field: rte_kni_mbuf::data_len", + ][::std::mem::offset_of!(rte_kni_mbuf, data_len) - 40usize]; + [ + "Offset of field: rte_kni_mbuf::pad3", + ][::std::mem::offset_of!(rte_kni_mbuf, pad3) - 64usize]; + [ + "Offset of field: rte_kni_mbuf::pool", + ][::std::mem::offset_of!(rte_kni_mbuf, pool) - 72usize]; + [ + "Offset of field: rte_kni_mbuf::next", + ][::std::mem::offset_of!(rte_kni_mbuf, next) - 80usize]; +}; +impl Default for rte_kni_mbuf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs b/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs new file mode 100644 index 0000000000..0ccd40a5f8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs @@ -0,0 +1,357 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +pub const RTE_CACHE_LINE_SIZE: u32 = 64; +pub const RTE_LIBRTE_IP_FRAG_MAX_FRAG: u32 = 4; +pub const IP_LAST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_LAST_FRAG_IDX; +pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX; +pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM; +pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_1 { + ///< index of last fragment + IP_LAST_FRAG_IDX = 0, + ///< index of first fragment + IP_FIRST_FRAG_IDX = 1, + ///< minimum number of fragments + IP_MIN_FRAG_NUM = 2, + IP_MAX_FRAG_NUM = 4, +} +/// @internal fragmented mbuf +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ip_frag { + ///< offset into the packet + pub ofs: u16, + ///< length of fragment + pub len: u16, + ///< fragment mbuf + pub mb: *mut rte_mbuf, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag"][::std::mem::size_of::() - 16usize]; + ["Alignment of ip_frag"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ip_frag::ofs"][::std::mem::offset_of!(ip_frag, ofs) - 0usize]; + ["Offset of field: ip_frag::len"][::std::mem::offset_of!(ip_frag, len) - 2usize]; + ["Offset of field: ip_frag::mb"][::std::mem::offset_of!(ip_frag, mb) - 8usize]; +}; +impl Default for ip_frag { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// @internal to uniquely indetify fragmented datagram. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ip_frag_key { + ///< src address, first 8 bytes used for IPv4 + pub src_dst: [u64; 4usize], + ///< dst address + pub id: u32, + ///< src/dst key length + pub key_len: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag_key"][::std::mem::size_of::() - 40usize]; + ["Alignment of ip_frag_key"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ip_frag_key::src_dst", + ][::std::mem::offset_of!(ip_frag_key, src_dst) - 0usize]; + [ + "Offset of field: ip_frag_key::id", + ][::std::mem::offset_of!(ip_frag_key, id) - 32usize]; + [ + "Offset of field: ip_frag_key::key_len", + ][::std::mem::offset_of!(ip_frag_key, key_len) - 36usize]; +}; +/** @internal Fragmented packet to reassemble. + First two entries in the frags[] array are for the last and first fragments.*/ +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone)] +pub struct ip_frag_pkt { + ///< LRU list + pub lru: ip_frag_pkt__bindgen_ty_1, + ///< fragmentation key + pub key: ip_frag_key, + ///< creation timestamp + pub start: u64, + ///< expected reassembled size + pub total_size: u32, + ///< size of fragments received + pub frag_size: u32, + ///< index of next entry to fill + pub last_idx: u32, + ///< fragments + pub frags: [ip_frag; 4usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ip_frag_pkt__bindgen_ty_1 { + pub tqe_next: *mut ip_frag_pkt, + pub tqe_prev: *mut *mut ip_frag_pkt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ip_frag_pkt__bindgen_ty_1", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of ip_frag_pkt__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ip_frag_pkt__bindgen_ty_1::tqe_next", + ][::std::mem::offset_of!(ip_frag_pkt__bindgen_ty_1, tqe_next) - 0usize]; + [ + "Offset of field: ip_frag_pkt__bindgen_ty_1::tqe_prev", + ][::std::mem::offset_of!(ip_frag_pkt__bindgen_ty_1, tqe_prev) - 8usize]; +}; +impl Default for ip_frag_pkt__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag_pkt"][::std::mem::size_of::() - 192usize]; + ["Alignment of ip_frag_pkt"][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: ip_frag_pkt::lru", + ][::std::mem::offset_of!(ip_frag_pkt, lru) - 0usize]; + [ + "Offset of field: ip_frag_pkt::key", + ][::std::mem::offset_of!(ip_frag_pkt, key) - 16usize]; + [ + "Offset of field: ip_frag_pkt::start", + ][::std::mem::offset_of!(ip_frag_pkt, start) - 56usize]; + [ + "Offset of field: ip_frag_pkt::total_size", + ][::std::mem::offset_of!(ip_frag_pkt, total_size) - 64usize]; + [ + "Offset of field: ip_frag_pkt::frag_size", + ][::std::mem::offset_of!(ip_frag_pkt, frag_size) - 68usize]; + [ + "Offset of field: ip_frag_pkt::last_idx", + ][::std::mem::offset_of!(ip_frag_pkt, last_idx) - 72usize]; + [ + "Offset of field: ip_frag_pkt::frags", + ][::std::mem::offset_of!(ip_frag_pkt, frags) - 80usize]; +}; +impl Default for ip_frag_pkt { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ip_pkt_list { + pub tqh_first: *mut ip_frag_pkt, + pub tqh_last: *mut *mut ip_frag_pkt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_pkt_list"][::std::mem::size_of::() - 16usize]; + ["Alignment of ip_pkt_list"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: ip_pkt_list::tqh_first", + ][::std::mem::offset_of!(ip_pkt_list, tqh_first) - 0usize]; + [ + "Offset of field: ip_pkt_list::tqh_last", + ][::std::mem::offset_of!(ip_pkt_list, tqh_last) - 8usize]; +}; +impl Default for ip_pkt_list { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// fragmentation table statistics +#[repr(C)] +#[repr(align(64))] +#[derive(Debug, Copy, Clone)] +pub struct ip_frag_tbl_stat { + ///< total # of find/insert attempts. + pub find_num: u64, + ///< # of add ops. + pub add_num: u64, + ///< # of del ops. + pub del_num: u64, + ///< # of reuse (del/add) ops. + pub reuse_num: u64, + ///< total # of add failures. + pub fail_total: u64, + ///< # of 'no space' add failures. + pub fail_nospace: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ip_frag_tbl_stat"][::std::mem::size_of::() - 64usize]; + [ + "Alignment of ip_frag_tbl_stat", + ][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: ip_frag_tbl_stat::find_num", + ][::std::mem::offset_of!(ip_frag_tbl_stat, find_num) - 0usize]; + [ + "Offset of field: ip_frag_tbl_stat::add_num", + ][::std::mem::offset_of!(ip_frag_tbl_stat, add_num) - 8usize]; + [ + "Offset of field: ip_frag_tbl_stat::del_num", + ][::std::mem::offset_of!(ip_frag_tbl_stat, del_num) - 16usize]; + [ + "Offset of field: ip_frag_tbl_stat::reuse_num", + ][::std::mem::offset_of!(ip_frag_tbl_stat, reuse_num) - 24usize]; + [ + "Offset of field: ip_frag_tbl_stat::fail_total", + ][::std::mem::offset_of!(ip_frag_tbl_stat, fail_total) - 32usize]; + [ + "Offset of field: ip_frag_tbl_stat::fail_nospace", + ][::std::mem::offset_of!(ip_frag_tbl_stat, fail_nospace) - 40usize]; +}; +impl Default for ip_frag_tbl_stat { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/// fragmentation table +#[repr(C)] +#[repr(align(64))] +#[derive(Debug)] +pub struct rte_ip_frag_tbl { + ///< ttl for table entries. + pub max_cycles: u64, + ///< hash value mask. + pub entry_mask: u32, + ///< max entries allowed. + pub max_entries: u32, + ///< entries in use. + pub use_entries: u32, + ///< hash assocaitivity. + pub bucket_entries: u32, + ///< total size of the table. + pub nb_entries: u32, + ///< num of associativity lines. + pub nb_buckets: u32, + ///< last used entry. + pub last: *mut ip_frag_pkt, + ///< LRU list for table entries. + pub lru: ip_pkt_list, + pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 8usize]>, + ///< statistics counters. + pub stat: ip_frag_tbl_stat, + ///< hash table. + pub pkt: __IncompleteArrayField, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_ip_frag_tbl"][::std::mem::size_of::() - 128usize]; + [ + "Alignment of rte_ip_frag_tbl", + ][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: rte_ip_frag_tbl::max_cycles", + ][::std::mem::offset_of!(rte_ip_frag_tbl, max_cycles) - 0usize]; + [ + "Offset of field: rte_ip_frag_tbl::entry_mask", + ][::std::mem::offset_of!(rte_ip_frag_tbl, entry_mask) - 8usize]; + [ + "Offset of field: rte_ip_frag_tbl::max_entries", + ][::std::mem::offset_of!(rte_ip_frag_tbl, max_entries) - 12usize]; + [ + "Offset of field: rte_ip_frag_tbl::use_entries", + ][::std::mem::offset_of!(rte_ip_frag_tbl, use_entries) - 16usize]; + [ + "Offset of field: rte_ip_frag_tbl::bucket_entries", + ][::std::mem::offset_of!(rte_ip_frag_tbl, bucket_entries) - 20usize]; + [ + "Offset of field: rte_ip_frag_tbl::nb_entries", + ][::std::mem::offset_of!(rte_ip_frag_tbl, nb_entries) - 24usize]; + [ + "Offset of field: rte_ip_frag_tbl::nb_buckets", + ][::std::mem::offset_of!(rte_ip_frag_tbl, nb_buckets) - 28usize]; + [ + "Offset of field: rte_ip_frag_tbl::last", + ][::std::mem::offset_of!(rte_ip_frag_tbl, last) - 32usize]; + [ + "Offset of field: rte_ip_frag_tbl::lru", + ][::std::mem::offset_of!(rte_ip_frag_tbl, lru) - 40usize]; + [ + "Offset of field: rte_ip_frag_tbl::stat", + ][::std::mem::offset_of!(rte_ip_frag_tbl, stat) - 64usize]; + [ + "Offset of field: rte_ip_frag_tbl::pkt", + ][::std::mem::offset_of!(rte_ip_frag_tbl, pkt) - 128usize]; +}; +impl Default for rte_ip_frag_tbl { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +///< fragment mbuf +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct rte_mbuf { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/layout_mbuf.rs b/bindgen-tests/tests/expectations/tests/layout_mbuf.rs new file mode 100644 index 0000000000..ce6c58e39e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/layout_mbuf.rs @@ -0,0 +1,1228 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +pub const RTE_CACHE_LINE_MIN_SIZE: u32 = 64; +pub const RTE_CACHE_LINE_SIZE: u32 = 64; +pub type phys_addr_t = u64; +pub type MARKER = [*mut ::std::os::raw::c_void; 0usize]; +pub type MARKER8 = [u8; 0usize]; +pub type MARKER64 = [u64; 0usize]; +/// The atomic counter structure. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_atomic16_t { + ///< An internal counter value. + pub cnt: i16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_atomic16_t"][::std::mem::size_of::() - 2usize]; + ["Alignment of rte_atomic16_t"][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_atomic16_t::cnt", + ][::std::mem::offset_of!(rte_atomic16_t, cnt) - 0usize]; +}; +/// The generic rte_mbuf, containing a packet mbuf. +#[repr(C)] +#[repr(align(64))] +pub struct rte_mbuf { + pub cacheline0: MARKER, + ///< Virtual address of segment buffer. + pub buf_addr: *mut ::std::os::raw::c_void, + ///< Physical address of segment buffer. + pub buf_physaddr: phys_addr_t, + ///< Length of segment buffer. + pub buf_len: u16, + pub rearm_data: MARKER8, + pub data_off: u16, + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, + ///< Number of segments. + pub nb_segs: u8, + ///< Input port. + pub port: u8, + ///< Offload features. + pub ol_flags: u64, + pub rx_descriptor_fields1: MARKER, + pub __bindgen_anon_2: rte_mbuf__bindgen_ty_2, + ///< Total pkt len: sum of all segments. + pub pkt_len: u32, + ///< Amount of data in segment buffer. + pub data_len: u16, + /// VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. + pub vlan_tci: u16, + ///< hash information + pub hash: rte_mbuf__bindgen_ty_3, + ///< Sequence number. See also rte_reorder_insert() + pub seqn: u32, + /// Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. + pub vlan_tci_outer: u16, + pub cacheline1: MARKER, + pub __bindgen_anon_3: rte_mbuf__bindgen_ty_4, + ///< Pool from which mbuf was allocated. + pub pool: *mut rte_mempool, + ///< Next segment of scattered packet. + pub next: *mut rte_mbuf, + pub __bindgen_anon_4: rte_mbuf__bindgen_ty_5, + /** Size of the application private data. In case of an indirect + mbuf, it stores the direct mbuf private data size.*/ + pub priv_size: u16, + /// Timesync flags for use with IEEE1588. + pub timesync: u16, +} +/** 16-bit Reference counter. + It should only be accessed using the following functions: + rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and + rte_mbuf_refcnt_set(). The functionality of these functions (atomic, + or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC + config option.*/ +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_1 { + ///< Atomically accessed refcnt + pub refcnt_atomic: rte_atomic16_t, + ///< Non-atomically accessed refcnt + pub refcnt: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_1", + ][::std::mem::size_of::() - 2usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_1::refcnt_atomic", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_1, refcnt_atomic) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_1::refcnt", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_1, refcnt) - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_2 { + ///< L2/L3/L4 and tunnel information. + pub packet_type: u32, + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_2__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mbuf__bindgen_ty_2__bindgen_ty_1 { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_2__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_2__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; +}; +impl rte_mbuf__bindgen_ty_2__bindgen_ty_1 { + #[inline] + pub fn l2_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } + } + #[inline] + pub fn set_l2_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn l2_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_l2_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn l3_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } + } + #[inline] + pub fn set_l3_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn l3_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_l3_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn l4_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u32) } + } + #[inline] + pub fn set_l4_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn l4_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_l4_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn tun_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 4u8) as u32) } + } + #[inline] + pub fn set_tun_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(12usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn tun_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 12usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_tun_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 12usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn inner_l2_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 4u8) as u32) } + } + #[inline] + pub fn set_inner_l2_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn inner_l2_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_inner_l2_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn inner_l3_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 4u8) as u32) } + } + #[inline] + pub fn set_inner_l3_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(20usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn inner_l3_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 20usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_inner_l3_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 20usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn inner_l4_type(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 4u8) as u32) } + } + #[inline] + pub fn set_inner_l4_type(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn inner_l4_type_raw(this: *const Self) -> u32 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_inner_l4_type_raw(this: *mut Self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + l2_type: u32, + l3_type: u32, + l4_type: u32, + tun_type: u32, + inner_l2_type: u32, + inner_l3_type: u32, + inner_l4_type: u32, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let l2_type: u32 = unsafe { ::std::mem::transmute(l2_type) }; + l2_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let l3_type: u32 = unsafe { ::std::mem::transmute(l3_type) }; + l3_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 4u8, + { + let l4_type: u32 = unsafe { ::std::mem::transmute(l4_type) }; + l4_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 12usize, + 4u8, + { + let tun_type: u32 = unsafe { ::std::mem::transmute(tun_type) }; + tun_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 4u8, + { + let inner_l2_type: u32 = unsafe { + ::std::mem::transmute(inner_l2_type) + }; + inner_l2_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 20usize, + 4u8, + { + let inner_l3_type: u32 = unsafe { + ::std::mem::transmute(inner_l3_type) + }; + inner_l3_type as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 4u8, + { + let inner_l4_type: u32 = unsafe { + ::std::mem::transmute(inner_l4_type) + }; + inner_l4_type as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_2::packet_type", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_2, packet_type) - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_3 { + ///< RSS hash result if RSS enabled + pub rss: u32, + ///< Filter identifier if FDIR enabled + pub fdir: rte_mbuf__bindgen_ty_3__bindgen_ty_1, + ///< Hierarchical scheduler + pub sched: rte_mbuf__bindgen_ty_3__bindgen_ty_2, + ///< User defined tags. See rte_distributor_process() + pub usr: u32, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1 { + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1, + pub hi: u32, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, + pub lo: u32, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { + pub hash: u16, + pub id: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::< + rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, + >() - 4usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::< + rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, + >() - 2usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1::hash", + ][::std::mem::offset_of!( + rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, hash + ) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1::id", + ][::std::mem::offset_of!( + rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, id + ) - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() + - 4usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() + - 4usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1::lo", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1, lo) + - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_3__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_3__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_1::hi", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3__bindgen_ty_1, hi) - 4usize]; +}; +impl Default for rte_mbuf__bindgen_ty_3__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_2 { + pub lo: u32, + pub hi: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_3__bindgen_ty_2", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_3__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_2::lo", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3__bindgen_ty_2, lo) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3__bindgen_ty_2::hi", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3__bindgen_ty_2, hi) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_3", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_3", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3::rss", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3, rss) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3::fdir", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3, fdir) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3::sched", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3, sched) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_3::usr", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_3, usr) - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_3 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_4 { + ///< Can be used for external metadata + pub userdata: *mut ::std::os::raw::c_void, + ///< Allow 8-byte userdata on 32-bit + pub udata64: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_4", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_4", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_4::userdata", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_4, userdata) - 0usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_4::udata64", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_4, udata64) - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_4 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union rte_mbuf__bindgen_ty_5 { + ///< combined for easy fetch + pub tx_offload: u64, + pub __bindgen_anon_1: rte_mbuf__bindgen_ty_5__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mbuf__bindgen_ty_5__bindgen_ty_1 { + pub _bindgen_align: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 7usize]>, + pub __bindgen_padding_0: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_5__bindgen_ty_1", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_5__bindgen_ty_1", + ][::std::mem::align_of::() - 8usize]; +}; +impl rte_mbuf__bindgen_ty_5__bindgen_ty_1 { + #[inline] + pub fn l2_len(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u64) } + } + #[inline] + pub fn set_l2_len(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn l2_len_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 7u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_l2_len_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn l3_len(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 9u8) as u64) } + } + #[inline] + pub fn set_l3_len(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 9u8, val as u64) + } + } + #[inline] + pub unsafe fn l3_len_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 9u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_l3_len_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 9u8, + val as u64, + ) + } + } + #[inline] + pub fn l4_len(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u64) } + } + #[inline] + pub fn set_l4_len(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn l4_len_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 8u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_l4_len_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn tso_segsz(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 16u8) as u64) } + } + #[inline] + pub fn set_tso_segsz(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(24usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn tso_segsz_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 24usize, 16u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_tso_segsz_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 24usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn outer_l3_len(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 9u8) as u64) } + } + #[inline] + pub fn set_outer_l3_len(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(40usize, 9u8, val as u64) + } + } + #[inline] + pub unsafe fn outer_l3_len_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 40usize, 9u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_outer_l3_len_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 40usize, + 9u8, + val as u64, + ) + } + } + #[inline] + pub fn outer_l2_len(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(49usize, 7u8) as u64) } + } + #[inline] + pub fn set_outer_l2_len(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(49usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn outer_l2_len_raw(this: *const Self) -> u64 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 49usize, 7u8) + as u64, + ) + } + } + #[inline] + pub unsafe fn set_outer_l2_len_raw(this: *mut Self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 7usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 49usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + l2_len: u64, + l3_len: u64, + l4_len: u64, + tso_segsz: u64, + outer_l3_len: u64, + outer_l2_len: u64, + ) -> __BindgenBitfieldUnit<[u8; 7usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 7usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 7u8, + { + let l2_len: u64 = unsafe { ::std::mem::transmute(l2_len) }; + l2_len as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 9u8, + { + let l3_len: u64 = unsafe { ::std::mem::transmute(l3_len) }; + l3_len as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 8u8, + { + let l4_len: u64 = unsafe { ::std::mem::transmute(l4_len) }; + l4_len as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 24usize, + 16u8, + { + let tso_segsz: u64 = unsafe { ::std::mem::transmute(tso_segsz) }; + tso_segsz as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 40usize, + 9u8, + { + let outer_l3_len: u64 = unsafe { + ::std::mem::transmute(outer_l3_len) + }; + outer_l3_len as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 49usize, + 7u8, + { + let outer_l2_len: u64 = unsafe { + ::std::mem::transmute(outer_l2_len) + }; + outer_l2_len as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of rte_mbuf__bindgen_ty_5", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of rte_mbuf__bindgen_ty_5", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: rte_mbuf__bindgen_ty_5::tx_offload", + ][::std::mem::offset_of!(rte_mbuf__bindgen_ty_5, tx_offload) - 0usize]; +}; +impl Default for rte_mbuf__bindgen_ty_5 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of rte_mbuf"][::std::mem::size_of::() - 128usize]; + ["Alignment of rte_mbuf"][::std::mem::align_of::() - 64usize]; + [ + "Offset of field: rte_mbuf::cacheline0", + ][::std::mem::offset_of!(rte_mbuf, cacheline0) - 0usize]; + [ + "Offset of field: rte_mbuf::buf_addr", + ][::std::mem::offset_of!(rte_mbuf, buf_addr) - 0usize]; + [ + "Offset of field: rte_mbuf::buf_physaddr", + ][::std::mem::offset_of!(rte_mbuf, buf_physaddr) - 8usize]; + [ + "Offset of field: rte_mbuf::buf_len", + ][::std::mem::offset_of!(rte_mbuf, buf_len) - 16usize]; + [ + "Offset of field: rte_mbuf::rearm_data", + ][::std::mem::offset_of!(rte_mbuf, rearm_data) - 18usize]; + [ + "Offset of field: rte_mbuf::data_off", + ][::std::mem::offset_of!(rte_mbuf, data_off) - 18usize]; + [ + "Offset of field: rte_mbuf::nb_segs", + ][::std::mem::offset_of!(rte_mbuf, nb_segs) - 22usize]; + [ + "Offset of field: rte_mbuf::port", + ][::std::mem::offset_of!(rte_mbuf, port) - 23usize]; + [ + "Offset of field: rte_mbuf::ol_flags", + ][::std::mem::offset_of!(rte_mbuf, ol_flags) - 24usize]; + [ + "Offset of field: rte_mbuf::rx_descriptor_fields1", + ][::std::mem::offset_of!(rte_mbuf, rx_descriptor_fields1) - 32usize]; + [ + "Offset of field: rte_mbuf::pkt_len", + ][::std::mem::offset_of!(rte_mbuf, pkt_len) - 36usize]; + [ + "Offset of field: rte_mbuf::data_len", + ][::std::mem::offset_of!(rte_mbuf, data_len) - 40usize]; + [ + "Offset of field: rte_mbuf::vlan_tci", + ][::std::mem::offset_of!(rte_mbuf, vlan_tci) - 42usize]; + [ + "Offset of field: rte_mbuf::hash", + ][::std::mem::offset_of!(rte_mbuf, hash) - 44usize]; + [ + "Offset of field: rte_mbuf::seqn", + ][::std::mem::offset_of!(rte_mbuf, seqn) - 52usize]; + [ + "Offset of field: rte_mbuf::vlan_tci_outer", + ][::std::mem::offset_of!(rte_mbuf, vlan_tci_outer) - 56usize]; + [ + "Offset of field: rte_mbuf::cacheline1", + ][::std::mem::offset_of!(rte_mbuf, cacheline1) - 64usize]; + [ + "Offset of field: rte_mbuf::pool", + ][::std::mem::offset_of!(rte_mbuf, pool) - 72usize]; + [ + "Offset of field: rte_mbuf::next", + ][::std::mem::offset_of!(rte_mbuf, next) - 80usize]; + [ + "Offset of field: rte_mbuf::priv_size", + ][::std::mem::offset_of!(rte_mbuf, priv_size) - 96usize]; + [ + "Offset of field: rte_mbuf::timesync", + ][::std::mem::offset_of!(rte_mbuf, timesync) - 98usize]; +}; +impl Default for rte_mbuf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +///< Pool from which mbuf was allocated. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct rte_mempool { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs b/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs new file mode 100644 index 0000000000..098beb43de --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub static mut b: ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/constified-enum-module-overflow.rs b/bindgen-tests/tests/expectations/tests/libclang-9/constified-enum-module-overflow.rs new file mode 100644 index 0000000000..4f8296c65c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/constified-enum-module-overflow.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct B { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub _address: u8, +} +pub type C_U = B; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub u: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; + ["Offset of field: A::u"][::std::mem::offset_of!(A, u) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: C_open0_A_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: C_open0_A_close0", + ][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/issue-544-stylo-creduce-2.rs b/bindgen-tests/tests/expectations/tests/libclang-9/issue-544-stylo-creduce-2.rs new file mode 100644 index 0000000000..d64a8948ee --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/issue-544-stylo-creduce-2.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + pub member: *mut __BindgenOpaqueArray<[u8; 0usize]>, +} +pub type Foo_FirstAlias = __BindgenOpaqueArray<[u8; 0usize]>; +pub type Foo_SecondAlias = __BindgenOpaqueArray<[u8; 0usize]>; +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/issue-753.rs b/bindgen-tests/tests/expectations/tests/libclang-9/issue-753.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/issue-753.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/macro_fallback_non_system_dir.rs b/bindgen-tests/tests/expectations/tests/libclang-9/macro_fallback_non_system_dir.rs new file mode 100644 index 0000000000..8f5c4ba2da --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/macro_fallback_non_system_dir.rs @@ -0,0 +1 @@ +pub const NEGATIVE: i32 = -1; diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/ptr32-has-different-size.rs b/bindgen-tests/tests/expectations/tests/libclang-9/ptr32-has-different-size.rs new file mode 100644 index 0000000000..f55f88f496 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/ptr32-has-different-size.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TEST_STRUCT { + pub ptr_32bit: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TEST_STRUCT"][::std::mem::size_of::() - 8usize]; + ["Alignment of TEST_STRUCT"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: TEST_STRUCT::ptr_32bit", + ][::std::mem::offset_of!(TEST_STRUCT, ptr_32bit) - 0usize]; +}; +impl Default for TEST_STRUCT { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type TEST = TEST_STRUCT; diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/struct_typedef_ns.rs b/bindgen-tests/tests/expectations/tests/libclang-9/struct_typedef_ns.rs new file mode 100644 index 0000000000..d93a62e746 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang-9/struct_typedef_ns.rs @@ -0,0 +1,57 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod whatever { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct typedef_struct { + pub foo: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of typedef_struct"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of typedef_struct", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: typedef_struct::foo", + ][::std::mem::offset_of!(typedef_struct, foo) - 0usize]; + }; + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum typedef_enum { + BAR = 1, + } + } + pub mod _bindgen_mod_id_12 { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct _bindgen_ty_1 { + pub foo: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 4usize]; + [ + "Alignment of _bindgen_ty_1", + ][::std::mem::align_of::<_bindgen_ty_1>() - 4usize]; + [ + "Offset of field: _bindgen_ty_1::foo", + ][::std::mem::offset_of!(_bindgen_ty_1, foo) - 0usize]; + }; + pub type typedef_struct = root::_bindgen_mod_id_12::_bindgen_ty_1; + pub const _bindgen_mod_id_12_BAR: root::_bindgen_mod_id_12::_bindgen_ty_2 = _bindgen_ty_2::BAR; + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum _bindgen_ty_2 { + BAR = 1, + } + pub use self::super::super::root::_bindgen_mod_id_12::_bindgen_ty_2 as typedef_enum; + } +} diff --git a/bindgen-tests/tests/expectations/tests/libclang_version_specific_generated_tests.rs b/bindgen-tests/tests/expectations/tests/libclang_version_specific_generated_tests.rs new file mode 100644 index 0000000000..2643709c04 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/libclang_version_specific_generated_tests.rs @@ -0,0 +1,4 @@ +include!(concat!( + env!("OUT_DIR"), + "/libclang_version_specific_generated_tests.rs" +)); diff --git a/bindgen-tests/tests/expectations/tests/long_double.rs b/bindgen-tests/tests/expectations/tests/long_double.rs new file mode 100644 index 0000000000..4a8b13e9b0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/long_double.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub bar: u128, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 16usize]; + ["Alignment of foo"][::std::mem::align_of::() - 16usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; diff --git a/tests/expectations/tests/macro-expr-basic.rs b/bindgen-tests/tests/expectations/tests/macro-expr-basic.rs similarity index 88% rename from tests/expectations/tests/macro-expr-basic.rs rename to bindgen-tests/tests/expectations/tests/macro-expr-basic.rs index 55590ff677..21c81b317c 100644 --- a/tests/expectations/tests/macro-expr-basic.rs +++ b/bindgen-tests/tests/expectations/tests/macro-expr-basic.rs @@ -1,7 +1,4 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - pub const FOO: u32 = 1; pub const BAR: u32 = 4; pub const BAZ: u32 = 5; diff --git a/bindgen-tests/tests/expectations/tests/macro-expr-uncommon-token.rs b/bindgen-tests/tests/expectations/tests/macro-expr-uncommon-token.rs new file mode 100644 index 0000000000..785ef4bb9f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/macro-expr-uncommon-token.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const MODBUS_WOOT: u32 = 3; +unsafe extern "C" { + pub fn foo(); +} diff --git a/tests/expectations/tests/macro-redef.rs b/bindgen-tests/tests/expectations/tests/macro-redef.rs similarity index 76% rename from tests/expectations/tests/macro-redef.rs rename to bindgen-tests/tests/expectations/tests/macro-redef.rs index e71322323e..12e3d3d587 100644 --- a/tests/expectations/tests/macro-redef.rs +++ b/bindgen-tests/tests/expectations/tests/macro-redef.rs @@ -1,7 +1,4 @@ -/* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - pub const FOO: u32 = 4; pub const BAR: u32 = 5; pub const BAZ: u32 = 6; diff --git a/bindgen-tests/tests/expectations/tests/macro_const.rs b/bindgen-tests/tests/expectations/tests/macro_const.rs new file mode 100644 index 0000000000..e4e27dea52 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/macro_const.rs @@ -0,0 +1,8 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const foo: &[u8; 4] = b"bar\0"; +pub const CHAR: u8 = 98u8; +pub const CHARR: u8 = 0u8; +pub const FLOAT: f64 = 5.09; +pub const FLOAT_EXPR: f64 = 0.005; +pub const LONG: u32 = 3; +pub const INVALID_UTF8: &[u8; 5] = b"\xF0(\x8C(\0"; diff --git a/tests/expectations/tests/maddness-is-avoidable.rs b/bindgen-tests/tests/expectations/tests/maddness-is-avoidable.rs similarity index 84% rename from tests/expectations/tests/maddness-is-avoidable.rs rename to bindgen-tests/tests/expectations/tests/maddness-is-avoidable.rs index b1eea1d093..0876aeb904 100644 --- a/tests/expectations/tests/maddness-is-avoidable.rs +++ b/bindgen-tests/tests/expectations/tests/maddness-is-avoidable.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct RefPtr { diff --git a/bindgen-tests/tests/expectations/tests/mangling-ios.rs b/bindgen-tests/tests/expectations/tests/mangling-ios.rs new file mode 100644 index 0000000000..736d379f01 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-ios.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} diff --git a/bindgen-tests/tests/expectations/tests/mangling-linux32.rs b/bindgen-tests/tests/expectations/tests/mangling-linux32.rs new file mode 100644 index 0000000000..b6ed9146da --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-linux32.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo4sBarE"] + pub static mut Foo_sBar: bool; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/mangling-linux64.rs b/bindgen-tests/tests/expectations/tests/mangling-linux64.rs new file mode 100644 index 0000000000..b6ed9146da --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-linux64.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo4sBarE"] + pub static mut Foo_sBar: bool; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/mangling-macos.rs b/bindgen-tests/tests/expectations/tests/mangling-macos.rs new file mode 100644 index 0000000000..237859e23b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-macos.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}__ZN3Foo4sBarE"] + pub static mut Foo_sBar: bool; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/mangling-win32.rs b/bindgen-tests/tests/expectations/tests/mangling-win32.rs new file mode 100644 index 0000000000..263f619374 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-win32.rs @@ -0,0 +1,39 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target = "i686-pc-windows-msvc")] +unsafe extern "C" { + pub fn foo(); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}?sBar@Foo@@2_NA"] + pub static mut Foo_sBar: bool; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "fastcall" { + pub fn fast_call_func_no_args() -> ::std::os::raw::c_int; +} +unsafe extern "fastcall" { + pub fn fast_call_func_many_args( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +unsafe extern "stdcall" { + pub fn std_call_func_no_args() -> ::std::os::raw::c_int; +} +unsafe extern "stdcall" { + pub fn std_call_func_many_args( + arg1: ::std::os::raw::c_int, + arg2: ::std::os::raw::c_int, + arg3: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/mangling-win64.rs b/bindgen-tests/tests/expectations/tests/mangling-win64.rs new file mode 100644 index 0000000000..2a782480ed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mangling-win64.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}?sBar@Foo@@2_NA"] + pub static mut Foo_sBar: bool; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/merge_extern_blocks_post_1_82.rs b/bindgen-tests/tests/expectations/tests/merge_extern_blocks_post_1_82.rs new file mode 100644 index 0000000000..98659f6382 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/merge_extern_blocks_post_1_82.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 4usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + }; + pub mod ns { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 4usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + }; + unsafe extern "C" { + #[link_name = "\u{1}_ZN2ns3fooEv"] + pub fn foo() -> ::std::os::raw::c_int; + #[link_name = "\u{1}_ZN2ns3barEv"] + pub fn bar() -> ::std::os::raw::c_int; + } + } + unsafe extern "C" { + #[link_name = "\u{1}_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; + #[link_name = "\u{1}_Z3barv"] + pub fn bar() -> ::std::os::raw::c_int; + } +} diff --git a/bindgen-tests/tests/expectations/tests/merge_extern_blocks_pre_1_82.rs b/bindgen-tests/tests/expectations/tests/merge_extern_blocks_pre_1_82.rs new file mode 100644 index 0000000000..595d865af1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/merge_extern_blocks_pre_1_82.rs @@ -0,0 +1,44 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 4usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + }; + pub mod ns { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 4usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + }; + extern "C" { + #[link_name = "\u{1}_ZN2ns3fooEv"] + pub fn foo() -> ::std::os::raw::c_int; + #[link_name = "\u{1}_ZN2ns3barEv"] + pub fn bar() -> ::std::os::raw::c_int; + } + } + extern "C" { + #[link_name = "\u{1}_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; + #[link_name = "\u{1}_Z3barv"] + pub fn bar() -> ::std::os::raw::c_int; + } +} diff --git a/bindgen-tests/tests/expectations/tests/method-mangling.rs b/bindgen-tests/tests/expectations/tests/method-mangling.rs new file mode 100644 index 0000000000..4c86825cce --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/method-mangling.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Foo4typeEv"] + pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn type_(&mut self) -> ::std::os::raw::c_int { + Foo_type(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/module-allowlisted.rs b/bindgen-tests/tests/expectations/tests/module-allowlisted.rs new file mode 100644 index 0000000000..9ac408dc8f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/module-allowlisted.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Test { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Test"][::std::mem::size_of::() - 1usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/msvc-no-usr.rs b/bindgen-tests/tests/expectations/tests/msvc-no-usr.rs new file mode 100644 index 0000000000..adaa1a07b2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/msvc-no-usr.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub foo: usize, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 8usize]; + ["Alignment of A"][::std::mem::align_of::() - 8usize]; + ["Offset of field: A::foo"][::std::mem::offset_of!(A, foo) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs b/bindgen-tests/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs new file mode 100644 index 0000000000..b0cf27451c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 1usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/mutable.rs b/bindgen-tests/tests/expectations/tests/mutable.rs new file mode 100644 index 0000000000..ff98d31f24 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/mutable.rs @@ -0,0 +1,45 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub m_member: ::std::os::raw::c_int, + pub m_other: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 8usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::m_member"][::std::mem::offset_of!(C, m_member) - 0usize]; + ["Offset of field: C::m_other"][::std::mem::offset_of!(C, m_other) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct NonCopiable { + pub m_member: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NonCopiable"][::std::mem::size_of::() - 4usize]; + ["Alignment of NonCopiable"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: NonCopiable::m_member", + ][::std::mem::offset_of!(NonCopiable, m_member) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct NonCopiableWithNonCopiableMutableMember { + pub m_member: NonCopiable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of NonCopiableWithNonCopiableMutableMember", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of NonCopiableWithNonCopiableMutableMember", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: NonCopiableWithNonCopiableMutableMember::m_member", + ][::std::mem::offset_of!(NonCopiableWithNonCopiableMutableMember, m_member) + - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/namespace.rs b/bindgen-tests/tests/expectations/tests/namespace.rs new file mode 100644 index 0000000000..4e58fa7ab1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/namespace.rs @@ -0,0 +1,101 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_Z9top_levelv"] + pub fn top_level(); + } + pub mod whatever { + #[allow(unused_imports)] + use self::super::super::root; + pub type whatever_other_thing_t = whatever_int_t; + pub type whatever_int_t = ::std::os::raw::c_int; + unsafe extern "C" { + #[link_name = "\u{1}_ZN8whatever11in_whateverEv"] + pub fn in_whatever(); + } + } + pub mod _bindgen_mod_id_17 { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct A { + pub b: root::whatever::whatever_int_t, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of A"][::std::mem::size_of::() - 4usize]; + ["Alignment of A"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A::b"][::std::mem::offset_of!(A, b) - 0usize]; + }; + } + #[repr(C)] + #[derive(Debug)] + pub struct C { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: root::_bindgen_mod_id_17::A, + pub m_c: T, + pub m_c_ptr: *mut T, + pub m_c_arr: [T; 10usize], + } + impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + pub mod w { + #[allow(unused_imports)] + use self::super::super::root; + pub type whatever_int_t = ::std::os::raw::c_uint; + #[repr(C)] + #[derive(Debug)] + pub struct D { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_c: root::C, + } + impl Default for D { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN1w3hehEv"] + pub fn heh() -> root::w::whatever_int_t; + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN1w3fooEv"] + pub fn foo() -> root::C<::std::os::raw::c_int>; + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN1w4barrEv"] + pub fn barr() -> root::C; + } + } + pub mod foobar { + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN6foobar3fooEv"] + pub fn foo(); + } + } + pub mod faraway { + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN7faraway3barEv"] + pub fn bar(); + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/nested-class-field.rs b/bindgen-tests/tests/expectations/tests/nested-class-field.rs new file mode 100644 index 0000000000..91500f4142 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nested-class-field.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A_I { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A_I"][::std::mem::size_of::() - 4usize]; + ["Alignment of A_I"][::std::mem::align_of::() - 4usize]; + ["Offset of field: A_I::i"][::std::mem::offset_of!(A_I, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/nested-template-typedef.rs b/bindgen-tests/tests/expectations/tests/nested-template-typedef.rs new file mode 100644 index 0000000000..4a4dd2ffe1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nested-template-typedef.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo_Bar { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/nested.rs b/bindgen-tests/tests/expectations/tests/nested.rs new file mode 100644 index 0000000000..5e0a8b07c8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nested.rs @@ -0,0 +1,53 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Calc { + pub w: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Calc"][::std::mem::size_of::() - 4usize]; + ["Alignment of Calc"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Calc::w"][::std::mem::offset_of!(Calc, w) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test_Size { + pub mWidth: Test_Size_Dimension, + pub mHeight: Test_Size_Dimension, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test_Size_Dimension { + pub _base: Calc, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of Test_Size_Dimension", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of Test_Size_Dimension", + ][::std::mem::align_of::() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test_Size"][::std::mem::size_of::() - 8usize]; + ["Alignment of Test_Size"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Test_Size::mWidth", + ][::std::mem::offset_of!(Test_Size, mWidth) - 0usize]; + [ + "Offset of field: Test_Size::mHeight", + ][::std::mem::offset_of!(Test_Size, mHeight) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 1usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/nested_vtable.rs b/bindgen-tests/tests/expectations/tests/nested_vtable.rs new file mode 100644 index 0000000000..12aa2ea441 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nested_vtable.rs @@ -0,0 +1,70 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct nsISupports__bindgen_vtable { + pub nsISupports_QueryInterface: unsafe extern "C" fn( + this: *mut nsISupports, + ) -> *mut nsISupports, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsISupports { + pub vtable_: *const nsISupports__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsISupports"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsISupports"][::std::mem::align_of::() - 8usize]; +}; +impl Default for nsISupports { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN11nsISupports14QueryInterfaceEv"] + pub fn nsISupports_QueryInterface( + this: *mut ::std::os::raw::c_void, + ) -> *mut nsISupports; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsIRunnable { + pub _base: nsISupports, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsIRunnable"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsIRunnable"][::std::mem::align_of::() - 8usize]; +}; +impl Default for nsIRunnable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Runnable { + pub _base: nsIRunnable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Runnable"][::std::mem::size_of::() - 8usize]; + ["Alignment of Runnable"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Runnable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/nested_within_namespace.rs b/bindgen-tests/tests/expectations/tests/nested_within_namespace.rs new file mode 100644 index 0000000000..f470571ddc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nested_within_namespace.rs @@ -0,0 +1,45 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar { + pub foo: ::std::os::raw::c_int, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar_Baz { + pub foo: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar_Baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar_Baz"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Bar_Baz::foo", + ][::std::mem::offset_of!(Bar_Baz, foo) - 0usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::foo"][::std::mem::offset_of!(Bar, foo) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Baz { + pub baz: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 4usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Baz::baz"][::std::mem::offset_of!(Baz, baz) - 0usize]; + }; + } +} diff --git a/bindgen-tests/tests/expectations/tests/new-type-alias.rs b/bindgen-tests/tests/expectations/tests/new-type-alias.rs new file mode 100644 index 0000000000..f63069cbe2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/new-type-alias.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const true_: u32 = 1; +#[repr(transparent)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo(pub u64); +pub const Foo_A: Foo = Foo(1); +#[repr(transparent)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar(pub ::std::os::raw::c_char); +pub const Bar_A: Bar = Bar(97); +#[repr(transparent)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz(pub f32); +pub const Baz_A: Baz = Baz(3.25); +#[repr(transparent)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bang(pub bool); +pub const Bang_A: Bang = Bang(true); +pub type Boom = u64; +pub const Boom_A: Boom = 2; diff --git a/bindgen-tests/tests/expectations/tests/newtype-enum.rs b/bindgen-tests/tests/expectations/tests/newtype-enum.rs new file mode 100644 index 0000000000..0045c52a61 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/newtype-enum.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl Foo { + pub const Bar: Foo = Foo(2); + pub const Baz: Foo = Foo(4); + pub const Duplicated: Foo = Foo(4); + pub const Negative: Foo = Foo(-3); +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_int); diff --git a/bindgen-tests/tests/expectations/tests/newtype-global-enum.rs b/bindgen-tests/tests/expectations/tests/newtype-global-enum.rs new file mode 100644 index 0000000000..29b87bff06 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/newtype-global-enum.rs @@ -0,0 +1,8 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const Foo_Bar: Foo = Foo(2); +pub const Foo_Baz: Foo = Foo(4); +pub const Foo_Duplicated: Foo = Foo(4); +pub const Foo_Negative: Foo = Foo(-3); +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Foo(pub ::std::os::raw::c_int); diff --git a/bindgen-tests/tests/expectations/tests/no-comments.rs b/bindgen-tests/tests/expectations/tests/no-comments.rs new file mode 100644 index 0000000000..6a60973fb4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-comments.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub s: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Foo::s"][::std::mem::offset_of!(Foo, s) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-derive-debug.rs b/bindgen-tests/tests/expectations/tests/no-derive-debug.rs new file mode 100644 index 0000000000..5e525068fd --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-derive-debug.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct foo { + bar: ::std::os::raw::c_int, +} +/** bar should compile. It will normally derive debug, but our blocklist of foo + and replacement for another type that doesn't implement it would prevent it + from building if --no-derive-debug didn't work.*/ +#[repr(C)] +pub struct bar { + pub foo: foo, + pub baz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar::foo"][::std::mem::offset_of!(bar, foo) - 0usize]; + ["Offset of field: bar::baz"][::std::mem::offset_of!(bar, baz) - 4usize]; +}; +impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/no-derive-default.rs b/bindgen-tests/tests/expectations/tests/no-derive-default.rs new file mode 100644 index 0000000000..a1d86a6502 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-derive-default.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct foo { + bar: ::std::os::raw::c_int, +} +/** bar should compile. It will normally derive default, but our blocklist of foo + and replacement for another type that doesn't implement it would prevent it + from building if --no-derive-default didn't work.*/ +#[repr(C)] +pub struct bar { + pub foo: foo, + pub baz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar::foo"][::std::mem::offset_of!(bar, foo) - 0usize]; + ["Offset of field: bar::baz"][::std::mem::offset_of!(bar, baz) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-hash-allowlisted.rs b/bindgen-tests/tests/expectations/tests/no-hash-allowlisted.rs new file mode 100644 index 0000000000..ff4dd1e38e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-hash-allowlisted.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoHash"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoHash"][::std::mem::align_of::() - 4usize]; + ["Offset of field: NoHash::i"][::std::mem::offset_of!(NoHash, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-hash-opaque.rs b/bindgen-tests/tests/expectations/tests/no-hash-opaque.rs new file mode 100644 index 0000000000..9dc9e01989 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-hash-opaque.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoHash"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoHash"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-partialeq-allowlisted.rs b/bindgen-tests/tests/expectations/tests/no-partialeq-allowlisted.rs new file mode 100644 index 0000000000..68ae1a7449 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-partialeq-allowlisted.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoPartialEq { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoPartialEq"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoPartialEq"][::std::mem::align_of::() - 4usize]; + ["Offset of field: NoPartialEq::i"][::std::mem::offset_of!(NoPartialEq, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-partialeq-opaque.rs b/bindgen-tests/tests/expectations/tests/no-partialeq-opaque.rs new file mode 100644 index 0000000000..4b488df6a5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-partialeq-opaque.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoPartialEq { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoPartialEq"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoPartialEq"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no-recursive-allowlisting.rs b/bindgen-tests/tests/expectations/tests/no-recursive-allowlisting.rs new file mode 100644 index 0000000000..dc1e4721ab --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-recursive-allowlisting.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub enum Bar {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + pub baz: *mut Bar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Foo::baz"][::std::mem::offset_of!(Foo, baz) - 0usize]; +}; +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/no-std.rs b/bindgen-tests/tests/expectations/tests/no-std.rs new file mode 100644 index 0000000000..0f03c222ef --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no-std.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![no_std] +mod libc { + pub type c_int = i32; + pub enum c_void {} +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub a: libc::c_int, + pub b: libc::c_int, + pub bar: *mut libc::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::core::mem::size_of::() - 16usize]; + ["Alignment of foo"][::core::mem::align_of::() - 8usize]; + ["Offset of field: foo::a"][::core::mem::offset_of!(foo, a) - 0usize]; + ["Offset of field: foo::b"][::core::mem::offset_of!(foo, b) - 4usize]; + ["Offset of field: foo::bar"][::core::mem::offset_of!(foo, bar) - 8usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/no_copy.rs b/bindgen-tests/tests/expectations/tests/no_copy.rs similarity index 81% rename from tests/expectations/tests/no_copy.rs rename to bindgen-tests/tests/expectations/tests/no_copy.rs index 452496682d..b92c542482 100644 --- a/tests/expectations/tests/no_copy.rs +++ b/bindgen-tests/tests/expectations/tests/no_copy.rs @@ -1,10 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - ///
#[repr(C)] #[derive(Debug, Default)] diff --git a/bindgen-tests/tests/expectations/tests/no_copy_allowlisted.rs b/bindgen-tests/tests/expectations/tests/no_copy_allowlisted.rs new file mode 100644 index 0000000000..67be391799 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_copy_allowlisted.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct NoCopy { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoCopy"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoCopy"][::std::mem::align_of::() - 4usize]; + ["Offset of field: NoCopy::i"][::std::mem::offset_of!(NoCopy, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_copy_opaque.rs b/bindgen-tests/tests/expectations/tests/no_copy_opaque.rs new file mode 100644 index 0000000000..dea6a0a6cf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_copy_opaque.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default)] +pub struct NoCopy { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoCopy"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoCopy"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_debug.rs b/bindgen-tests/tests/expectations/tests/no_debug.rs new file mode 100644 index 0000000000..9a162c6f70 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_debug.rs @@ -0,0 +1,7 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct DebugButWait { + pub whatever: ::std::os::raw::c_int, +} diff --git a/bindgen-tests/tests/expectations/tests/no_debug_allowlisted.rs b/bindgen-tests/tests/expectations/tests/no_debug_allowlisted.rs new file mode 100644 index 0000000000..1ddb20a747 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_debug_allowlisted.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct NoDebug { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoDebug"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoDebug"][::std::mem::align_of::() - 4usize]; + ["Offset of field: NoDebug::i"][::std::mem::offset_of!(NoDebug, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_debug_bypass_impl_debug.rs b/bindgen-tests/tests/expectations/tests/no_debug_bypass_impl_debug.rs new file mode 100644 index 0000000000..ceec3823ae --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_debug_bypass_impl_debug.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug)] +pub struct Generic { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: [T; 40usize], +} +impl Default for Generic { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct NoDebug { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: [T; 40usize], +} +impl Default for NoDebug { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/no_debug_opaque.rs b/bindgen-tests/tests/expectations/tests/no_debug_opaque.rs new file mode 100644 index 0000000000..0bb37ec711 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_debug_opaque.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(4))] +#[derive(Default, Copy, Clone)] +pub struct NoDebug { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoDebug"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoDebug"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_default.rs b/bindgen-tests/tests/expectations/tests/no_default.rs new file mode 100644 index 0000000000..fd3d86e277 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_default.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DefaultButWait { + pub whatever: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DefaultButWaitDerived { + pub whatever: DefaultButWait, +} +impl Default for DefaultButWaitDerived { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/no_default_allowlisted.rs b/bindgen-tests/tests/expectations/tests/no_default_allowlisted.rs new file mode 100644 index 0000000000..593e644343 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_default_allowlisted.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NoDefault { + pub i: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoDefault"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoDefault"][::std::mem::align_of::() - 4usize]; + ["Offset of field: NoDefault::i"][::std::mem::offset_of!(NoDefault, i) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_default_bypass_derive_default.rs b/bindgen-tests/tests/expectations/tests/no_default_bypass_derive_default.rs new file mode 100644 index 0000000000..3dfd34474a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_default_bypass_derive_default.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug)] +pub struct Generic { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: [T; 40usize], +} +impl Default for Generic { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug)] +pub struct NoDefault { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: [T; 40usize], +} diff --git a/bindgen-tests/tests/expectations/tests/no_default_opaque.rs b/bindgen-tests/tests/expectations/tests/no_default_opaque.rs new file mode 100644 index 0000000000..ba2f63f91c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_default_opaque.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Copy, Clone)] +pub struct NoDefault { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NoDefault"][::std::mem::size_of::() - 4usize]; + ["Alignment of NoDefault"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/no_size_t_is_usize.rs b/bindgen-tests/tests/expectations/tests/no_size_t_is_usize.rs new file mode 100644 index 0000000000..94ce735b31 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/no_size_t_is_usize.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type size_t = ::std::os::raw::c_ulong; +pub type ssize_t = ::std::os::raw::c_long; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct A { + pub len: size_t, + pub offset: ssize_t, + pub next: *mut A, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::
() - 24usize]; + ["Alignment of A"][::std::mem::align_of::() - 8usize]; + ["Offset of field: A::len"][::std::mem::offset_of!(A, len) - 0usize]; + ["Offset of field: A::offset"][::std::mem::offset_of!(A, offset) - 8usize]; + ["Offset of field: A::next"][::std::mem::offset_of!(A, next) - 16usize]; +}; +impl Default for A { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/non-type-params.rs b/bindgen-tests/tests/expectations/tests/non-type-params.rs new file mode 100644 index 0000000000..325620b9bb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/non-type-params.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +pub type Array16 = u8; +pub type ArrayInt4 = __BindgenOpaqueArray<[u32; 4usize]>; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct UsesArray { + pub array_char_16: __BindgenOpaqueArray<[u8; 16usize]>, + pub array_bool_8: __BindgenOpaqueArray<[u8; 8usize]>, + pub array_int_4: ArrayInt4, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of UsesArray"][::std::mem::size_of::() - 40usize]; + ["Alignment of UsesArray"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: UsesArray::array_char_16", + ][::std::mem::offset_of!(UsesArray, array_char_16) - 0usize]; + [ + "Offset of field: UsesArray::array_bool_8", + ][::std::mem::offset_of!(UsesArray, array_bool_8) - 16usize]; + [ + "Offset of field: UsesArray::array_int_4", + ][::std::mem::offset_of!(UsesArray, array_int_4) - 24usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/noreturn.rs b/bindgen-tests/tests/expectations/tests/noreturn.rs new file mode 100644 index 0000000000..0e601b5510 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/noreturn.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z1fv"] + pub fn f() -> !; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z1gv"] + pub fn g() -> !; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z1hv"] + pub fn h() -> !; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z1iPFvvE"] + pub fn i(arg: ::std::option::Option !>); +} +unsafe extern "C" { + #[link_name = "\u{1}_Z1jPFvvE"] + pub fn j(arg: ::std::option::Option !>) -> !; +} diff --git a/bindgen-tests/tests/expectations/tests/nsBaseHashtable.rs b/bindgen-tests/tests/expectations/tests/nsBaseHashtable.rs new file mode 100644 index 0000000000..81b9f000c6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nsBaseHashtable.rs @@ -0,0 +1,65 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct nsBaseHashtableET { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct nsTHashtable { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsBaseHashtable { + pub _address: u8, +} +pub type nsBaseHashtable_KeyType = __BindgenOpaqueArray<[u8; 0usize]>; +pub type nsBaseHashtable_EntryType = nsBaseHashtableET; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsBaseHashtable_LookupResult { + pub mEntry: *mut nsBaseHashtable_EntryType, + pub mTable: *mut nsBaseHashtable, +} +impl Default for nsBaseHashtable_LookupResult { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug)] +pub struct nsBaseHashtable_EntryPtr { + pub mEntry: *mut nsBaseHashtable_EntryType, + pub mExistingEntry: bool, +} +impl Default for nsBaseHashtable_EntryPtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for nsBaseHashtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/nsStyleAutoArray.rs b/bindgen-tests/tests/expectations/tests/nsStyleAutoArray.rs new file mode 100644 index 0000000000..3d8edcfdc1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/nsStyleAutoArray.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub mBuff: *mut T, +} +impl Default for nsTArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsStyleAutoArray { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub mFirstElement: T, + pub mOtherElements: nsTArray, +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum nsStyleAutoArray_WithSingleInitialElement { + WITH_SINGLE_INITIAL_ELEMENT = 0, +} +impl Default for nsStyleAutoArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_allowlist.rs b/bindgen-tests/tests/expectations/tests/objc_allowlist.rs new file mode 100644 index 0000000000..7ccd4e3c04 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_allowlist.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait PSomeProtocol: Sized + std::ops::Deref { + unsafe fn protocolMethod(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, protocolMethod) + } + unsafe fn protocolClassMethod() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(SomeProtocol), protocolClassMethod) + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct AllowlistMe(pub id); +impl std::ops::Deref for AllowlistMe { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for AllowlistMe {} +impl AllowlistMe { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(AllowlistMe), alloc) }) + } +} +impl PSomeProtocol for AllowlistMe {} +impl IAllowlistMe for AllowlistMe {} +pub trait IAllowlistMe: Sized + std::ops::Deref { + unsafe fn method(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, method) + } + unsafe fn classMethod() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(AllowlistMe), classMethod) + } +} +impl AllowlistMe_InterestingCategory for AllowlistMe {} +pub trait AllowlistMe_InterestingCategory: Sized + std::ops::Deref {} diff --git a/bindgen-tests/tests/expectations/tests/objc_blocklist.rs b/bindgen-tests/tests/expectations/tests/objc_blocklist.rs new file mode 100644 index 0000000000..e5c5d2bfd5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_blocklist.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +#[macro_use] +extern crate objc; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct SomeClass(pub id); +impl std::ops::Deref for SomeClass { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for SomeClass {} +impl SomeClass { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(SomeClass), alloc) }) + } +} +impl ISomeClass for SomeClass {} +pub trait ISomeClass: Sized + std::ops::Deref { + unsafe fn ambiguouslyBlockedMethod(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, ambiguouslyBlockedMethod) + } + unsafe fn instanceMethod(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, instanceMethod) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_category.rs b/bindgen-tests/tests/expectations/tests/objc_category.rs new file mode 100644 index 0000000000..a1b1e3b1f1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_category.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, method) + } +} +impl Foo_BarCategory for Foo {} +pub trait Foo_BarCategory: Sized + std::ops::Deref { + unsafe fn categoryMethod(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, categoryMethod) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_class.rs b/bindgen-tests/tests/expectations/tests/objc_class.rs new file mode 100644 index 0000000000..a7346d1ee9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_class.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +unsafe extern "C" { + pub static mut fooVar: Foo; +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, method) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_class_method.rs b/bindgen-tests/tests/expectations/tests/objc_class_method.rs new file mode 100644 index 0000000000..6bc2621462 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_class_method.rs @@ -0,0 +1,65 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), method) + } + unsafe fn methodWithInt_(foo: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodWithInt : foo) + } + unsafe fn methodWithFoo_(foo: Foo) + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodWithFoo : foo) + } + unsafe fn methodReturningInt() -> ::std::os::raw::c_int + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodReturningInt) + } + unsafe fn methodReturningFoo() -> Foo + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodReturningFoo) + } + unsafe fn methodWithArg1_andArg2_andArg3_( + intvalue: ::std::os::raw::c_int, + ptr: *mut ::std::os::raw::c_char, + floatvalue: f32, + ) + where + ::Target: objc::Message + Sized, + { + msg_send!( + class!(Foo), methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue + ) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_escape.rs b/bindgen-tests/tests/expectations/tests/objc_escape.rs new file mode 100644 index 0000000000..1351231d62 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_escape.rs @@ -0,0 +1,65 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct A(pub id); +impl std::ops::Deref for A { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for A {} +impl A { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(A), alloc) }) + } +} +impl IA for A {} +pub trait IA: Sized + std::ops::Deref { + unsafe fn f_as_(&self, arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, f : arg1 r#as : arg2) + } + unsafe fn crate_(&self, self_: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, crate_ : self_) + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct B(pub id); +impl std::ops::Deref for B { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for B {} +impl B { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(B), alloc) }) + } +} +impl IB for B {} +pub trait IB: Sized + std::ops::Deref { + unsafe fn type_(&self) -> id + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, type) + } + unsafe fn setType_(&self, type_: id) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, setType : type_) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_inheritance.rs b/bindgen-tests/tests/expectations/tests/objc_inheritance.rs new file mode 100644 index 0000000000..6fb4e6b857 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_inheritance.rs @@ -0,0 +1,107 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Bar(pub id); +impl std::ops::Deref for Bar { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Bar {} +impl Bar { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Bar), alloc) }) + } +} +impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = unsafe { msg_send!(parent, isKindOfClass : class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} +impl IBar for Bar {} +pub trait IBar: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Baz(pub id); +impl std::ops::Deref for Baz { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Baz {} +impl Baz { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Baz), alloc) }) + } +} +impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Bar) -> Result { + let is_kind_of: bool = unsafe { msg_send!(parent, isKindOfClass : class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Bar cannot be downcasted to Baz") + } + } +} +impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = unsafe { msg_send!(parent, isKindOfClass : class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Foo cannot be downcasted to Baz") + } + } +} +impl IBaz for Baz {} +pub trait IBaz: Sized + std::ops::Deref {} diff --git a/bindgen-tests/tests/expectations/tests/objc_interface.rs b/bindgen-tests/tests/expectations/tests/objc_interface.rs new file mode 100644 index 0000000000..2cc602efd4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_interface.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} +pub trait Pbar: Sized + std::ops::Deref {} diff --git a/bindgen-tests/tests/expectations/tests/objc_interface_type.rs b/bindgen-tests/tests/expectations/tests/objc_interface_type.rs new file mode 100644 index 0000000000..56ad75ed25 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_interface_type.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct FooStruct { + pub foo: Foo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of FooStruct"][::std::mem::size_of::() - 8usize]; + ["Alignment of FooStruct"][::std::mem::align_of::() - 8usize]; + ["Offset of field: FooStruct::foo"][::std::mem::offset_of!(FooStruct, foo) - 0usize]; +}; +impl Default for FooStruct { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + pub fn fooFunc(foo: Foo); +} +unsafe extern "C" { + pub static mut kFoo: Foo; +} diff --git a/bindgen-tests/tests/expectations/tests/objc_method.rs b/bindgen-tests/tests/expectations/tests/objc_method.rs new file mode 100644 index 0000000000..7d9fd84cf2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_method.rs @@ -0,0 +1,80 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, method) + } + unsafe fn methodWithInt_(&self, foo: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodWithInt : foo) + } + unsafe fn methodWithFoo_(&self, foo: Foo) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodWithFoo : foo) + } + unsafe fn methodReturningInt(&self) -> ::std::os::raw::c_int + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodReturningInt) + } + unsafe fn methodReturningFoo(&self) -> Foo + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodReturningFoo) + } + unsafe fn methodWithArg1_andArg2_andArg3_( + &self, + intvalue: ::std::os::raw::c_int, + ptr: *mut ::std::os::raw::c_char, + floatvalue: f32, + ) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue) + } + unsafe fn methodWithAndWithoutKeywords_arg2Name__arg4Name_( + &self, + arg1: ::std::os::raw::c_int, + arg2: f32, + arg3: f32, + arg4: ::std::os::raw::c_int, + ) -> instancetype + where + ::Target: objc::Message + Sized, + { + msg_send!( + * self, methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 + arg4Name : arg4 + ) + } +} +pub type instancetype = id; diff --git a/bindgen-tests/tests/expectations/tests/objc_method_clash.rs b/bindgen-tests/tests/expectations/tests/objc_method_clash.rs new file mode 100644 index 0000000000..4d35661f8c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_method_clash.rs @@ -0,0 +1,35 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn foo(&self) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, foo) + } + unsafe fn class_foo() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), foo) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_pointer_return_types.rs b/bindgen-tests/tests/expectations/tests/objc_pointer_return_types.rs new file mode 100644 index 0000000000..73c3d6e5c8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_pointer_return_types.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Bar(pub id); +impl std::ops::Deref for Bar { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Bar {} +impl Bar { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Bar), alloc) }) + } +} +impl IBar for Bar {} +pub trait IBar: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn methodUsingBar_(&self, my_bar: Bar) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, methodUsingBar : my_bar) + } + unsafe fn methodReturningBar() -> Bar + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodReturningBar) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_property_fnptr.rs b/bindgen-tests/tests/expectations/tests/objc_property_fnptr.rs new file mode 100644 index 0000000000..e038edf7f1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_property_fnptr.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn func( + &self, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: ::std::os::raw::c_char, + arg2: ::std::os::raw::c_short, + arg3: f32, + ) -> ::std::os::raw::c_int, + > + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, func) + } + unsafe fn setFunc_( + &self, + func: ::std::option::Option< + unsafe extern "C" fn( + arg1: ::std::os::raw::c_char, + arg2: ::std::os::raw::c_short, + arg3: f32, + ) -> ::std::os::raw::c_int, + >, + ) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, setFunc : func) + } +} diff --git a/bindgen-tests/tests/expectations/tests/objc_protocol.rs b/bindgen-tests/tests/expectations/tests/objc_protocol.rs new file mode 100644 index 0000000000..533f5e2ef3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_protocol.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait PFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl PFoo for Foo {} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} diff --git a/bindgen-tests/tests/expectations/tests/objc_protocol_inheritance.rs b/bindgen-tests/tests/expectations/tests/objc_protocol_inheritance.rs new file mode 100644 index 0000000000..8bb0ef6f62 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_protocol_inheritance.rs @@ -0,0 +1,59 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait PFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl PFoo for Foo {} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Bar(pub id); +impl std::ops::Deref for Bar { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Bar {} +impl Bar { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Bar), alloc) }) + } +} +impl IFoo for Bar {} +impl PFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = unsafe { msg_send!(parent, isKindOfClass : class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} +impl IBar for Bar {} +pub trait IBar: Sized + std::ops::Deref {} diff --git a/bindgen-tests/tests/expectations/tests/objc_sel_and_id.rs b/bindgen-tests/tests/expectations/tests/objc_sel_and_id.rs new file mode 100644 index 0000000000..cf38af4e64 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_sel_and_id.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +unsafe extern "C" { + pub static mut object: id; +} +unsafe extern "C" { + pub static mut selector: objc::runtime::Sel; +} +unsafe extern "C" { + pub fn f(object: id, selector: objc::runtime::Sel); +} diff --git a/bindgen-tests/tests/expectations/tests/objc_template.rs b/bindgen-tests/tests/expectations/tests/objc_template.rs new file mode 100644 index 0000000000..1c70009df3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/objc_template.rs @@ -0,0 +1,68 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(&self) -> __BindgenOpaqueArray8<[u8; 8usize]> + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, get) + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(FooMultiGeneric), alloc) }) + } +} +impl IFooMultiGeneric +for FooMultiGeneric {} +pub trait IFooMultiGeneric< + KeyType: 'static, + ObjectType: 'static, +>: Sized + std::ops::Deref { + unsafe fn objectForKey_( + &self, + key: __BindgenOpaqueArray8<[u8; 8usize]>, + ) -> __BindgenOpaqueArray8<[u8; 8usize]> + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, objectForKey : key) + } +} diff --git a/bindgen-tests/tests/expectations/tests/only_bitfields.rs b/bindgen-tests/tests/expectations/tests/only_bitfields.rs new file mode 100644 index 0000000000..9a73fc2fee --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/only_bitfields.rs @@ -0,0 +1,252 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 1usize]; + ["Alignment of C"][::std::mem::align_of::() - 1usize]; +}; +impl C { + #[inline] + pub fn a(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 7u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u8 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 7u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/opaque-template-inst-member-2.rs b/bindgen-tests/tests/expectations/tests/opaque-template-inst-member-2.rs new file mode 100644 index 0000000000..14718a9312 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque-template-inst-member-2.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** This is like `opaque-template-inst-member.hpp` except exercising the cases + where we are OK to derive Debug/Hash/PartialEq.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct OpaqueTemplate { + pub _address: u8, +} +/// Should derive Debug/Hash/PartialEq. +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ContainsOpaqueTemplate { + pub mBlah: u32, + pub mBaz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsOpaqueTemplate", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of ContainsOpaqueTemplate", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContainsOpaqueTemplate::mBlah", + ][::std::mem::offset_of!(ContainsOpaqueTemplate, mBlah) - 0usize]; + [ + "Offset of field: ContainsOpaqueTemplate::mBaz", + ][::std::mem::offset_of!(ContainsOpaqueTemplate, mBaz) - 4usize]; +}; +/// Should also derive Debug/Hash/PartialEq. +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct InheritsOpaqueTemplate { + pub _base: u8, + pub wow: *mut ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of InheritsOpaqueTemplate", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of InheritsOpaqueTemplate", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: InheritsOpaqueTemplate::wow", + ][::std::mem::offset_of!(InheritsOpaqueTemplate, wow) - 8usize]; +}; +impl Default for InheritsOpaqueTemplate { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/opaque-template-inst-member.rs b/bindgen-tests/tests/expectations/tests/opaque-template-inst-member.rs new file mode 100644 index 0000000000..f765f01150 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque-template-inst-member.rs @@ -0,0 +1,66 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct OpaqueTemplate { + pub _address: u8, +} +/** This should not end up deriving Debug/Hash because its `mBlah` field cannot derive + Debug/Hash because the instantiation's definition cannot derive Debug/Hash.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ContainsOpaqueTemplate { + pub mBlah: __BindgenOpaqueArray<[u32; 101usize]>, + pub mBaz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsOpaqueTemplate", + ][::std::mem::size_of::() - 408usize]; + [ + "Alignment of ContainsOpaqueTemplate", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContainsOpaqueTemplate::mBlah", + ][::std::mem::offset_of!(ContainsOpaqueTemplate, mBlah) - 0usize]; + [ + "Offset of field: ContainsOpaqueTemplate::mBaz", + ][::std::mem::offset_of!(ContainsOpaqueTemplate, mBaz) - 404usize]; +}; +/** This should not end up deriving Debug/Hash either, for similar reasons, although + we're exercising base member edges now.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct InheritsOpaqueTemplate { + pub _base: __BindgenOpaqueArray<[u8; 401usize]>, + pub wow: *mut ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of InheritsOpaqueTemplate", + ][::std::mem::size_of::() - 416usize]; + [ + "Alignment of InheritsOpaqueTemplate", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: InheritsOpaqueTemplate::wow", + ][::std::mem::offset_of!(InheritsOpaqueTemplate, wow) - 408usize]; +}; +impl Default for InheritsOpaqueTemplate { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs new file mode 100644 index 0000000000..58644e053d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs @@ -0,0 +1,101 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod zoidberg { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct Template { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, + } + impl Default for Template { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct Foo { + pub c: ::std::os::raw::c_char, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Foo::c"][::std::mem::offset_of!(Foo, c) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct Bar { + pub i: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::i"][::std::mem::offset_of!(Bar, i) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct ContainsInstantiation { + pub not_opaque: root::zoidberg::Template, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of ContainsInstantiation", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ContainsInstantiation", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ContainsInstantiation::not_opaque", + ][::std::mem::offset_of!(ContainsInstantiation, not_opaque) - 0usize]; + }; + impl Default for ContainsInstantiation { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct ContainsOpaqueInstantiation { + pub opaque: u32, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of ContainsOpaqueInstantiation", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of ContainsOpaqueInstantiation", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContainsOpaqueInstantiation::opaque", + ][::std::mem::offset_of!(ContainsOpaqueInstantiation, opaque) - 0usize]; + }; + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of template specialization: Template_open0_Foo_close0", + ][::std::mem::size_of::>() + - 1usize]; + [ + "Align of template specialization: Template_open0_Foo_close0", + ][::std::mem::align_of::>() + - 1usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/opaque-template-instantiation.rs b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation.rs new file mode 100644 index 0000000000..ab68c21856 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation.rs @@ -0,0 +1,68 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Template { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, +} +impl Default for Template { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ContainsInstantiation { + pub not_opaque: Template<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsInstantiation", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of ContainsInstantiation", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ContainsInstantiation::not_opaque", + ][::std::mem::offset_of!(ContainsInstantiation, not_opaque) - 0usize]; +}; +impl Default for ContainsInstantiation { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ContainsOpaqueInstantiation { + pub opaque: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsOpaqueInstantiation", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of ContainsOpaqueInstantiation", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContainsOpaqueInstantiation::opaque", + ][::std::mem::offset_of!(ContainsOpaqueInstantiation, opaque) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Template_open0_char_close0", + ][::std::mem::size_of::>() - 1usize]; + [ + "Align of template specialization: Template_open0_char_close0", + ][::std::mem::align_of::>() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/opaque-tracing.rs b/bindgen-tests/tests/expectations/tests/opaque-tracing.rs new file mode 100644 index 0000000000..60d249a88c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque-tracing.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooP9Container"] + pub fn foo(c: *mut Container); +} +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Container { + pub _bindgen_opaque_blob: [u32; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Container"][::std::mem::size_of::() - 8usize]; + ["Alignment of Container"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/opaque_in_struct.rs b/bindgen-tests/tests/expectations/tests/opaque_in_struct.rs new file mode 100644 index 0000000000..b651cd3354 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque_in_struct.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct opaque { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of opaque"][::std::mem::size_of::() - 4usize]; + ["Alignment of opaque"][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct container { + pub contained: opaque, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of container"][::std::mem::size_of::() - 4usize]; + ["Alignment of container"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: container::contained", + ][::std::mem::offset_of!(container, contained) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/opaque_pointer.rs b/bindgen-tests/tests/expectations/tests/opaque_pointer.rs new file mode 100644 index 0000000000..ec519d9c6b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opaque_pointer.rs @@ -0,0 +1,49 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct OtherOpaque { + pub _bindgen_opaque_blob: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of OtherOpaque"][::std::mem::size_of::() - 4usize]; + ["Alignment of OtherOpaque"][::std::mem::align_of::() - 4usize]; +}; +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Opaque { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq)] +pub struct WithOpaquePtr { + pub whatever: *mut u8, + pub other: u32, + pub t: OtherOpaque, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithOpaquePtr"][::std::mem::size_of::() - 16usize]; + ["Alignment of WithOpaquePtr"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: WithOpaquePtr::whatever", + ][::std::mem::offset_of!(WithOpaquePtr, whatever) - 0usize]; + [ + "Offset of field: WithOpaquePtr::other", + ][::std::mem::offset_of!(WithOpaquePtr, other) - 8usize]; + [ + "Offset of field: WithOpaquePtr::t", + ][::std::mem::offset_of!(WithOpaquePtr, t) - 12usize]; +}; +impl Default for WithOpaquePtr { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/opaque_typedef.rs b/bindgen-tests/tests/expectations/tests/opaque_typedef.rs similarity index 86% rename from tests/expectations/tests/opaque_typedef.rs rename to bindgen-tests/tests/expectations/tests/opaque_typedef.rs index 96df276ccd..90c3b709e3 100644 --- a/tests/expectations/tests/opaque_typedef.rs +++ b/bindgen-tests/tests/expectations/tests/opaque_typedef.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct RandomTemplate { diff --git a/bindgen-tests/tests/expectations/tests/opencl_vector.rs b/bindgen-tests/tests/expectations/tests/opencl_vector.rs new file mode 100644 index 0000000000..3c2525c845 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/opencl_vector.rs @@ -0,0 +1,6 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type float4 = [f32; 4usize]; +pub type float2 = [f32; 2usize]; +unsafe extern "C" { + pub fn foo(a: float2, b: float2) -> float4; +} diff --git a/bindgen-tests/tests/expectations/tests/operator.rs b/bindgen-tests/tests/expectations/tests/operator.rs new file mode 100644 index 0000000000..ce5a652d8d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/operator.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z20operator_informationv"] + pub fn operator_information() -> ::std::os::raw::c_int; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/expectations/tests/operator_equals.rs b/bindgen-tests/tests/expectations/tests/operator_equals.rs new file mode 100644 index 0000000000..ff9f4fdd22 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/operator_equals.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct SomeClass { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of SomeClass"][::std::mem::size_of::() - 1usize]; + ["Alignment of SomeClass"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN9SomeClassaSERKS_"] + pub fn SomeClass_operatorequals( + this: *mut SomeClass, + another: *const SomeClass, + ) -> bool; +} +impl SomeClass { + #[inline] + pub unsafe fn operatorequals(&mut self, another: *const SomeClass) -> bool { + SomeClass_operatorequals(self, another) + } +} diff --git a/bindgen-tests/tests/expectations/tests/ord-enum.rs b/bindgen-tests/tests/expectations/tests/ord-enum.rs new file mode 100644 index 0000000000..aa2e67ab91 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/ord-enum.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum A { + A0 = 0, + A1 = 1, + A2 = 2, + A3 = -1, +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum B { + B0 = 1, + B1 = 4, + B2 = 3, + B3 = -1, +} diff --git a/bindgen-tests/tests/expectations/tests/overflowed_enum.rs b/bindgen-tests/tests/expectations/tests/overflowed_enum.rs new file mode 100644 index 0000000000..2c67ba6903 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/overflowed_enum.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Foo { + BAP_ARM = 9698489, + BAP_X86 = 11960045, + BAP_X86_64 = 3128633167, +} +#[repr(u16)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum Bar { + One = 1, + Big = 2, +} diff --git a/tests/expectations/tests/overloading.rs b/bindgen-tests/tests/expectations/tests/overloading.rs similarity index 81% rename from tests/expectations/tests/overloading.rs rename to bindgen-tests/tests/expectations/tests/overloading.rs index 28b783c334..96504b38eb 100644 --- a/tests/expectations/tests/overloading.rs +++ b/bindgen-tests/tests/expectations/tests/overloading.rs @@ -1,22 +1,17 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { +unsafe extern "C" { #[link_name = "\u{1}_Z8Evaluatec"] pub fn Evaluate(r: ::std::os::raw::c_char) -> bool; } -extern "C" { +unsafe extern "C" { #[link_name = "\u{1}_Z8Evaluateii"] pub fn Evaluate1(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) -> bool; } -extern "C" { +unsafe extern "C" { #[link_name = "\u{1}_ZN3foo10MyFunctionEv"] pub fn foo_MyFunction(); } -extern "C" { +unsafe extern "C" { #[link_name = "\u{1}_ZN3bar10MyFunctionEv"] pub fn bar_MyFunction(); } diff --git a/bindgen-tests/tests/expectations/tests/packed-bitfield.rs b/bindgen-tests/tests/expectations/tests/packed-bitfield.rs new file mode 100644 index 0000000000..b5a734454a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/packed-bitfield.rs @@ -0,0 +1,301 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Date { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Date"][::std::mem::size_of::() - 3usize]; + ["Alignment of Date"][::std::mem::align_of::() - 1usize]; +}; +impl Date { + #[inline] + pub fn day(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 5u8) as u8) } + } + #[inline] + pub fn set_day(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 5u8, val as u64) + } + } + #[inline] + pub unsafe fn day_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 5u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_day_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 5u8, + val as u64, + ) + } + } + #[inline] + pub fn month(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 4u8) as u8) } + } + #[inline] + pub fn set_month(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(5usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn month_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 5usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_month_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 5usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn year(&self) -> ::std::os::raw::c_short { + unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 15u8) as u16) } + } + #[inline] + pub fn set_year(&mut self, val: ::std::os::raw::c_short) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(9usize, 15u8, val as u64) + } + } + #[inline] + pub unsafe fn year_raw(this: *const Self) -> ::std::os::raw::c_short { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 9usize, 15u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_year_raw(this: *mut Self, val: ::std::os::raw::c_short) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 9usize, + 15u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + day: ::std::os::raw::c_uchar, + month: ::std::os::raw::c_uchar, + year: ::std::os::raw::c_short, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 5u8, + { + let day: u8 = unsafe { ::std::mem::transmute(day) }; + day as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 5usize, + 4u8, + { + let month: u8 = unsafe { ::std::mem::transmute(month) }; + month as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 9usize, + 15u8, + { + let year: u16 = unsafe { ::std::mem::transmute(year) }; + year as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/packed-n-with-padding.rs b/bindgen-tests/tests/expectations/tests/packed-n-with-padding.rs new file mode 100644 index 0000000000..162a1bebed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/packed-n-with-padding.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C, packed(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Packed { + pub a: ::std::os::raw::c_char, + pub b: ::std::os::raw::c_short, + pub c: ::std::os::raw::c_char, + pub d: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Packed"][::std::mem::size_of::() - 10usize]; + ["Alignment of Packed"][::std::mem::align_of::() - 2usize]; + ["Offset of field: Packed::a"][::std::mem::offset_of!(Packed, a) - 0usize]; + ["Offset of field: Packed::b"][::std::mem::offset_of!(Packed, b) - 2usize]; + ["Offset of field: Packed::c"][::std::mem::offset_of!(Packed, c) - 4usize]; + ["Offset of field: Packed::d"][::std::mem::offset_of!(Packed, d) - 6usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/packed-vtable.rs b/bindgen-tests/tests/expectations/tests/packed-vtable.rs new file mode 100644 index 0000000000..71e1956d88 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/packed-vtable.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#[repr(C)] +pub struct PackedVtable__bindgen_vtable(::std::os::raw::c_void); +#[repr(C, packed)] +pub struct PackedVtable { + pub vtable_: *const PackedVtable__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PackedVtable"][::std::mem::size_of::() - 8usize]; + ["Alignment of PackedVtable"][::std::mem::align_of::() - 1usize]; +}; +impl Default for PackedVtable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN12PackedVtableD1Ev"] + pub fn PackedVtable_PackedVtable_destructor(this: *mut PackedVtable); +} diff --git a/bindgen-tests/tests/expectations/tests/parm-union.rs b/bindgen-tests/tests/expectations/tests/parm-union.rs new file mode 100644 index 0000000000..6dee4ec7d5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/parm-union.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Struct { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Struct"][::std::mem::size_of::() - 1usize]; + ["Alignment of Struct"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN6Struct8FunctionER5Union"] + pub fn Struct_Function(this: *mut Struct, arg1: *mut Union); +} +impl Struct { + #[inline] + pub unsafe fn Function(&mut self, arg1: *mut Union) { + Struct_Function(self, arg1) + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Union { + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/expectations/tests/parsecb-anonymous-enum-variant-rename.rs b/bindgen-tests/tests/expectations/tests/parsecb-anonymous-enum-variant-rename.rs new file mode 100644 index 0000000000..98c10d7ec5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/parsecb-anonymous-enum-variant-rename.rs @@ -0,0 +1,3 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const RENAMED_MyVal: _bindgen_ty_1 = 0; +pub type _bindgen_ty_1 = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/partial-specialization-and-inheritance.rs b/bindgen-tests/tests/expectations/tests/partial-specialization-and-inheritance.rs new file mode 100644 index 0000000000..cba5cfbb52 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/partial-specialization-and-inheritance.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Base { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Derived { + pub b: bool, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Usage { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN5Usage13static_memberE"] + pub static mut Usage_static_member: __BindgenOpaqueArray<[u32; 2usize]>; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Usage"][::std::mem::size_of::() - 1usize]; + ["Alignment of Usage"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/pointer-attr.rs b/bindgen-tests/tests/expectations/tests/pointer-attr.rs new file mode 100644 index 0000000000..4d7e250b9c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/pointer-attr.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn a(arg1: *const ::std::os::raw::c_char); +} diff --git a/bindgen-tests/tests/expectations/tests/prefix-link-name-c.rs b/bindgen-tests/tests/expectations/tests/prefix-link-name-c.rs new file mode 100644 index 0000000000..cb1ebfa4f7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/prefix-link-name-c.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}foo_bar"] + pub fn bar() -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/prefix-link-name-cpp.rs b/bindgen-tests/tests/expectations/tests/prefix-link-name-cpp.rs new file mode 100644 index 0000000000..07cacc5f7a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/prefix-link-name-cpp.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}foo_foo"] + pub fn baz_foo() -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/prepend-enum-constified-variant.rs b/bindgen-tests/tests/expectations/tests/prepend-enum-constified-variant.rs new file mode 100644 index 0000000000..ff49d684f1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/prepend-enum-constified-variant.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +impl AVCodecID { + pub const AV_CODEC_ID_TTF: AVCodecID = AVCodecID::AV_CODEC_ID_FIRST_UNKNOWN; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AVCodecID { + AV_CODEC_ID_FIRST_UNKNOWN = 98304, +} diff --git a/bindgen-tests/tests/expectations/tests/prepend_enum_name.rs b/bindgen-tests/tests/expectations/tests/prepend_enum_name.rs new file mode 100644 index 0000000000..b4201a8cd9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/prepend_enum_name.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const FOO_BAR: foo = 0; +pub const FOO_BAZ: foo = 1; +pub type foo = ::std::os::raw::c_uint; diff --git a/bindgen-tests/tests/expectations/tests/private.rs b/bindgen-tests/tests/expectations/tests/private.rs new file mode 100644 index 0000000000..bf1e853e6a --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/private.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct HasPrivate { + pub mNotPrivate: ::std::os::raw::c_int, + ///
+ mIsPrivate: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of HasPrivate"][::std::mem::size_of::() - 8usize]; + ["Alignment of HasPrivate"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: HasPrivate::mNotPrivate", + ][::std::mem::offset_of!(HasPrivate, mNotPrivate) - 0usize]; + [ + "Offset of field: HasPrivate::mIsPrivate", + ][::std::mem::offset_of!(HasPrivate, mIsPrivate) - 4usize]; +}; +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct VeryPrivate { + mIsPrivate: ::std::os::raw::c_int, + mIsAlsoPrivate: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of VeryPrivate"][::std::mem::size_of::() - 8usize]; + ["Alignment of VeryPrivate"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: VeryPrivate::mIsPrivate", + ][::std::mem::offset_of!(VeryPrivate, mIsPrivate) - 0usize]; + [ + "Offset of field: VeryPrivate::mIsAlsoPrivate", + ][::std::mem::offset_of!(VeryPrivate, mIsAlsoPrivate) - 4usize]; +}; +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ContradictPrivate { + ///
+ pub mNotPrivate: ::std::os::raw::c_int, + mIsPrivate: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ContradictPrivate"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of ContradictPrivate", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: ContradictPrivate::mNotPrivate", + ][::std::mem::offset_of!(ContradictPrivate, mNotPrivate) - 0usize]; + [ + "Offset of field: ContradictPrivate::mIsPrivate", + ][::std::mem::offset_of!(ContradictPrivate, mIsPrivate) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/private_fields.rs b/bindgen-tests/tests/expectations/tests/private_fields.rs new file mode 100644 index 0000000000..abb2886d39 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/private_fields.rs @@ -0,0 +1,788 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PubPriv { + pub x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PubPriv"][::std::mem::size_of::() - 8usize]; + ["Alignment of PubPriv"][::std::mem::align_of::() - 4usize]; + ["Offset of field: PubPriv::x"][::std::mem::offset_of!(PubPriv, x) - 0usize]; + ["Offset of field: PubPriv::y"][::std::mem::offset_of!(PubPriv, y) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PrivateBitFields { + pub _bindgen_align: [u32; 0], + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PrivateBitFields"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of PrivateBitFields", + ][::std::mem::align_of::() - 4usize]; +}; +impl PrivateBitFields { + #[inline] + fn a(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } + } + #[inline] + fn set_a(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn b(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } + } + #[inline] + fn set_b(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + a: ::std::os::raw::c_uint, + b: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let a: u32 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let b: u32 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct PublicBitFields { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PublicBitFields"][::std::mem::size_of::() - 4usize]; + ["Alignment of PublicBitFields"][::std::mem::align_of::() - 4usize]; +}; +impl PublicBitFields { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_uint, + b: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let a: u32 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let b: u32 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct MixedBitFields { + pub _bindgen_align: [u32; 0], + _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of MixedBitFields"][::std::mem::size_of::() - 4usize]; + ["Alignment of MixedBitFields"][::std::mem::align_of::() - 4usize]; +}; +impl MixedBitFields { + #[inline] + fn a(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } + } + #[inline] + fn set_a(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn d(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } + } + #[inline] + pub fn set_d(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn d_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_d_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + a: ::std::os::raw::c_uint, + d: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let a: u32 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let d: u32 = unsafe { ::std::mem::transmute(d) }; + d as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Base { + pub member: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Base"][::std::mem::size_of::() - 4usize]; + ["Alignment of Base"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Base::member"][::std::mem::offset_of!(Base, member) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct InheritsPrivately { + _base: Base, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of InheritsPrivately"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of InheritsPrivately", + ][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct InheritsPublically { + pub _base: Base, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of InheritsPublically"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of InheritsPublically", + ][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithAnonStruct { + __bindgen_anon_1: WithAnonStruct__bindgen_ty_1, + pub __bindgen_anon_2: WithAnonStruct__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithAnonStruct__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of WithAnonStruct__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WithAnonStruct__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithAnonStruct__bindgen_ty_1::a", + ][::std::mem::offset_of!(WithAnonStruct__bindgen_ty_1, a) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WithAnonStruct__bindgen_ty_2 { + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of WithAnonStruct__bindgen_ty_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WithAnonStruct__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithAnonStruct__bindgen_ty_2::b", + ][::std::mem::offset_of!(WithAnonStruct__bindgen_ty_2, b) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithAnonStruct"][::std::mem::size_of::() - 8usize]; + ["Alignment of WithAnonStruct"][::std::mem::align_of::() - 4usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct WithAnonUnion { + __bindgen_anon_1: WithAnonUnion__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union WithAnonUnion__bindgen_ty_1 { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of WithAnonUnion__bindgen_ty_1", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of WithAnonUnion__bindgen_ty_1", + ][::std::mem::align_of::() - 1usize]; +}; +impl Default for WithAnonUnion__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithAnonUnion"][::std::mem::size_of::() - 1usize]; + ["Alignment of WithAnonUnion"][::std::mem::align_of::() - 1usize]; +}; +impl Default for WithAnonUnion { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Override { + pub a: ::std::os::raw::c_uint, + ///
+ b: ::std::os::raw::c_uint, + private_c: ::std::os::raw::c_uint, + _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub __bindgen_padding_0: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Override"][::std::mem::size_of::() - 16usize]; + ["Alignment of Override"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Override::a"][::std::mem::offset_of!(Override, a) - 0usize]; + ["Offset of field: Override::b"][::std::mem::offset_of!(Override, b) - 4usize]; + [ + "Offset of field: Override::private_c", + ][::std::mem::offset_of!(Override, private_c) - 8usize]; +}; +impl Override { + #[inline] + pub fn bf_a(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } + } + #[inline] + pub fn set_bf_a(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn bf_a_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bf_a_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn bf_b(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } + } + #[inline] + fn set_bf_b(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + unsafe fn bf_b_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_bf_b_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn private_bf_c(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u32) } + } + #[inline] + fn set_private_bf_c(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 4u8, val as u64) + } + } + #[inline] + unsafe fn private_bf_c_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 4u8) + as u32, + ) + } + } + #[inline] + unsafe fn set_private_bf_c_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 4u8, + val as u64, + ) + } + } + #[inline] + fn new_bitfield_1( + bf_a: ::std::os::raw::c_uint, + bf_b: ::std::os::raw::c_uint, + private_bf_c: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let bf_a: u32 = unsafe { ::std::mem::transmute(bf_a) }; + bf_a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let bf_b: u32 = unsafe { ::std::mem::transmute(bf_b) }; + bf_b as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 4u8, + { + let private_bf_c: u32 = unsafe { + ::std::mem::transmute(private_bf_c) + }; + private_bf_c as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/ptr32-has-different-size.rs b/bindgen-tests/tests/expectations/tests/ptr32-has-different-size.rs new file mode 100644 index 0000000000..f4f3ab4294 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/ptr32-has-different-size.rs @@ -0,0 +1,24 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TEST_STRUCT { + pub ptr_32bit: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of TEST_STRUCT"][::std::mem::size_of::() - 4usize]; + ["Alignment of TEST_STRUCT"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: TEST_STRUCT::ptr_32bit", + ][::std::mem::offset_of!(TEST_STRUCT, ptr_32bit) - 0usize]; +}; +impl Default for TEST_STRUCT { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type TEST = TEST_STRUCT; diff --git a/bindgen-tests/tests/expectations/tests/public-dtor.rs b/bindgen-tests/tests/expectations/tests/public-dtor.rs new file mode 100644 index 0000000000..578d3e76a5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/public-dtor.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct cv_Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cv_Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of cv_Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN2cv3FooD1Ev"] + pub fn cv_Foo_Foo_destructor(this: *mut cv_Foo); +} +impl cv_Foo { + #[inline] + pub unsafe fn destruct(&mut self) { + cv_Foo_Foo_destructor(self) + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct cv_Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cv_Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of cv_Bar"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/qualified-dependent-types.rs b/bindgen-tests/tests/expectations/tests/qualified-dependent-types.rs new file mode 100644 index 0000000000..9bbbddd88d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/qualified-dependent-types.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/redeclaration.rs b/bindgen-tests/tests/expectations/tests/redeclaration.rs new file mode 100644 index 0000000000..736d379f01 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/redeclaration.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo(); +} diff --git a/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs b/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs new file mode 100644 index 0000000000..05401e52ca --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs @@ -0,0 +1,372 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone)] +pub struct redundant_packed { + pub a: u32, + pub b: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of redundant_packed"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of redundant_packed", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: redundant_packed::a", + ][::std::mem::offset_of!(redundant_packed, a) - 0usize]; + [ + "Offset of field: redundant_packed::b", + ][::std::mem::offset_of!(redundant_packed, b) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct redundant_packed_bitfield { + pub _bindgen_align: [u64; 0], + pub a: [u8; 3usize], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub c: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of redundant_packed_bitfield", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of redundant_packed_bitfield", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: redundant_packed_bitfield::a", + ][::std::mem::offset_of!(redundant_packed_bitfield, a) - 0usize]; + [ + "Offset of field: redundant_packed_bitfield::c", + ][::std::mem::offset_of!(redundant_packed_bitfield, c) - 4usize]; +}; +impl redundant_packed_bitfield { + #[inline] + pub fn b0(&self) -> u8 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_b0(&mut self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b0_raw(this: *const Self) -> u8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b0_raw(this: *mut Self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b1(&self) -> u8 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } + } + #[inline] + pub fn set_b1(&mut self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b1_raw(this: *const Self) -> u8 { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b1_raw(this: *mut Self, val: u8) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(b0: u8, b1: u8) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let b0: u8 = unsafe { ::std::mem::transmute(b0) }; + b0 as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b1: u8 = unsafe { ::std::mem::transmute(b1) }; + b1 as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Copy, Clone)] +pub union redundant_packed_union { + pub a: u64, + pub b: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of redundant_packed_union", + ][::std::mem::size_of::() - 16usize]; + [ + "Alignment of redundant_packed_union", + ][::std::mem::align_of::() - 16usize]; + [ + "Offset of field: redundant_packed_union::a", + ][::std::mem::offset_of!(redundant_packed_union, a) - 0usize]; + [ + "Offset of field: redundant_packed_union::b", + ][::std::mem::offset_of!(redundant_packed_union, b) - 0usize]; +}; +impl Default for redundant_packed_union { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(2))] +#[derive(Debug, Default, Copy, Clone)] +pub struct inner { + pub a: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of inner"][::std::mem::size_of::() - 2usize]; + ["Alignment of inner"][::std::mem::align_of::() - 2usize]; + ["Offset of field: inner::a"][::std::mem::offset_of!(inner, a) - 0usize]; +}; +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone)] +pub struct outer_redundant_packed { + pub a: [inner; 2usize], + pub b: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of outer_redundant_packed", + ][::std::mem::size_of::() - 8usize]; + [ + "Alignment of outer_redundant_packed", + ][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: outer_redundant_packed::a", + ][::std::mem::offset_of!(outer_redundant_packed, a) - 0usize]; + [ + "Offset of field: outer_redundant_packed::b", + ][::std::mem::offset_of!(outer_redundant_packed, b) - 4usize]; +}; +#[repr(C)] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct redundant_pragma_packed { + pub a: u8, + pub b: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of redundant_pragma_packed", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of redundant_pragma_packed", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: redundant_pragma_packed::a", + ][::std::mem::offset_of!(redundant_pragma_packed, a) - 0usize]; + [ + "Offset of field: redundant_pragma_packed::b", + ][::std::mem::offset_of!(redundant_pragma_packed, b) - 2usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/ref_argument_array.rs b/bindgen-tests/tests/expectations/tests/ref_argument_array.rs new file mode 100644 index 0000000000..4928a185fe --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/ref_argument_array.rs @@ -0,0 +1,35 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const NSID_LENGTH: u32 = 10; +#[repr(C)] +pub struct nsID__bindgen_vtable { + pub nsID_ToProvidedString: unsafe extern "C" fn( + this: *mut nsID, + aDest: *mut [::std::os::raw::c_char; 10usize], + ), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsID { + pub vtable_: *const nsID__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsID"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsID"][::std::mem::align_of::() - 8usize]; +}; +impl Default for nsID { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4nsID16ToProvidedStringERA10_c"] + pub fn nsID_ToProvidedString( + this: *mut ::std::os::raw::c_void, + aDest: *mut [::std::os::raw::c_char; 10usize], + ); +} diff --git a/bindgen-tests/tests/expectations/tests/references.rs b/bindgen-tests/tests/expectations/tests/references.rs new file mode 100644 index 0000000000..799e855793 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/references.rs @@ -0,0 +1,61 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Container { + pub normalPointer: *mut ::std::os::raw::c_int, + pub constPointer: *const ::std::os::raw::c_int, + pub normalRef: ::std::ptr::NonNull<::std::os::raw::c_int>, + pub constRef: ::std::ptr::NonNull<::std::os::raw::c_int>, + pub pointerRef: ::std::ptr::NonNull<*mut ::std::os::raw::c_int>, + pub constPointerRef: ::std::ptr::NonNull<*const ::std::os::raw::c_int>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Container"][::std::mem::size_of::() - 48usize]; + ["Alignment of Container"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: Container::normalPointer", + ][::std::mem::offset_of!(Container, normalPointer) - 0usize]; + [ + "Offset of field: Container::constPointer", + ][::std::mem::offset_of!(Container, constPointer) - 8usize]; + [ + "Offset of field: Container::normalRef", + ][::std::mem::offset_of!(Container, normalRef) - 16usize]; + [ + "Offset of field: Container::constRef", + ][::std::mem::offset_of!(Container, constRef) - 24usize]; + [ + "Offset of field: Container::pointerRef", + ][::std::mem::offset_of!(Container, pointerRef) - 32usize]; + [ + "Offset of field: Container::constPointerRef", + ][::std::mem::offset_of!(Container, constPointerRef) - 40usize]; +}; +impl Default for Container { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z20refReturningFunctionv"] + pub fn refReturningFunction() -> ::std::ptr::NonNull<::std::os::raw::c_int>; +} +unsafe extern "C" { + #[link_name = "\u{1}_Z20functionConsumingRefRifRKi"] + pub fn functionConsumingRef( + someRef: ::std::ptr::NonNull<::std::os::raw::c_int>, + normalArgument: f32, + constRef: ::std::ptr::NonNull<::std::os::raw::c_int>, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_Z27functionConsumingPointerRefRPi"] + pub fn functionConsumingPointerRef( + pointerRef: ::std::ptr::NonNull<*mut ::std::os::raw::c_int>, + ); +} diff --git a/bindgen-tests/tests/expectations/tests/reparented_replacement.rs b/bindgen-tests/tests/expectations/tests/reparented_replacement.rs new file mode 100644 index 0000000000..9b2cc33ce9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/reparented_replacement.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + ///
+ #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Bar { + pub bazz: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::bazz"][::std::mem::offset_of!(Bar, bazz) - 0usize]; + }; + } + pub type ReferencesBar = root::foo::Bar; +} diff --git a/bindgen-tests/tests/expectations/tests/replace_template_alias.rs b/bindgen-tests/tests/expectations/tests/replace_template_alias.rs new file mode 100644 index 0000000000..2efa164ddf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/replace_template_alias.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** But the replacement type does use T! + +
*/ +pub type JS_detail_MaybeWrapped = T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct JS_Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: JS_detail_MaybeWrapped, +} +impl Default for JS_Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/replace_use.rs b/bindgen-tests/tests/expectations/tests/replace_use.rs new file mode 100644 index 0000000000..ebf9657176 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/replace_use.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct nsTArray { + pub y: ::std::os::raw::c_uint, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test { + pub a: nsTArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 4usize]; + ["Alignment of Test"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Test::a"][::std::mem::offset_of!(Test, a) - 0usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: nsTArray_open0_long_close0", + ][::std::mem::size_of::() - 4usize]; + [ + "Align of template specialization: nsTArray_open0_long_close0", + ][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/replaces_double.rs b/bindgen-tests/tests/expectations/tests/replaces_double.rs new file mode 100644 index 0000000000..e764113f21 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/replaces_double.rs @@ -0,0 +1,34 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Wrapper_Wrapped { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +impl Default for Wrapper_Wrapped { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type Wrapper_Type = Wrapper_Wrapped; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: Rooted_MaybeWrapped, +} +///
+pub type Rooted_MaybeWrapped = T; +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/repr-align.rs b/bindgen-tests/tests/expectations/tests/repr-align.rs new file mode 100644 index 0000000000..867a28cc78 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/repr-align.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone)] +pub struct a { + pub b: ::std::os::raw::c_int, + pub c: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of a"][::std::mem::size_of::
() - 8usize]; + ["Alignment of a"][::std::mem::align_of::() - 8usize]; + ["Offset of field: a::b"][::std::mem::offset_of!(a, b) - 0usize]; + ["Offset of field: a::c"][::std::mem::offset_of!(a, c) - 4usize]; +}; +#[repr(C)] +#[repr(align(8))] +#[derive(Debug, Default, Copy, Clone)] +pub struct b { + pub b: ::std::os::raw::c_int, + pub c: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of b"][::std::mem::size_of::() - 8usize]; + ["Alignment of b"][::std::mem::align_of::() - 8usize]; + ["Offset of field: b::b"][::std::mem::offset_of!(b, b) - 0usize]; + ["Offset of field: b::c"][::std::mem::offset_of!(b, c) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/resolved_type_def_function.rs b/bindgen-tests/tests/expectations/tests/resolved_type_def_function.rs new file mode 100644 index 0000000000..cfbab6b968 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/resolved_type_def_function.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type FuncType = ::std::option::Option; +unsafe extern "C" { + pub fn Func(); +} diff --git a/bindgen-tests/tests/expectations/tests/same_struct_name_in_different_namespaces.rs b/bindgen-tests/tests/expectations/tests/same_struct_name_in_different_namespaces.rs new file mode 100644 index 0000000000..e6e4088abf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/same_struct_name_in_different_namespaces.rs @@ -0,0 +1,23 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct JS_Zone { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct JS_shadow_Zone { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of JS_shadow_Zone"][::std::mem::size_of::() - 8usize]; + ["Alignment of JS_shadow_Zone"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: JS_shadow_Zone::x", + ][::std::mem::offset_of!(JS_shadow_Zone, x) - 0usize]; + [ + "Offset of field: JS_shadow_Zone::y", + ][::std::mem::offset_of!(JS_shadow_Zone, y) - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/sentry-defined-multiple-times.rs b/bindgen-tests/tests/expectations/tests/sentry-defined-multiple-times.rs new file mode 100644 index 0000000000..0fe153e700 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/sentry-defined-multiple-times.rs @@ -0,0 +1,235 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod whatever { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Wrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Wrapper_sentry { + pub i_am_wrapper_sentry: ::std::os::raw::c_int, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct sentry { + pub i_am_plain_sentry: bool, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of sentry"][::std::mem::size_of::() - 1usize]; + ["Alignment of sentry"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: sentry::i_am_plain_sentry", + ][::std::mem::offset_of!(sentry, i_am_plain_sentry) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct NotTemplateWrapper { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of NotTemplateWrapper", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of NotTemplateWrapper", + ][::std::mem::align_of::() - 1usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct NotTemplateWrapper_sentry { + pub i_am_not_template_wrapper_sentry: ::std::os::raw::c_char, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of NotTemplateWrapper_sentry", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of NotTemplateWrapper_sentry", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: NotTemplateWrapper_sentry::i_am_not_template_wrapper_sentry", + ][::std::mem::offset_of!( + NotTemplateWrapper_sentry, i_am_not_template_wrapper_sentry + ) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct InlineNotTemplateWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct InlineNotTemplateWrapper_sentry { + pub i_am_inline_not_template_wrapper_sentry: bool, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of InlineNotTemplateWrapper_sentry", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of InlineNotTemplateWrapper_sentry", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: InlineNotTemplateWrapper_sentry::i_am_inline_not_template_wrapper_sentry", + ][::std::mem::offset_of!( + InlineNotTemplateWrapper_sentry, i_am_inline_not_template_wrapper_sentry + ) - 0usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of InlineNotTemplateWrapper", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of InlineNotTemplateWrapper", + ][::std::mem::align_of::() - 1usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct InlineTemplateWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct InlineTemplateWrapper_sentry { + pub i_am_inline_template_wrapper_sentry: ::std::os::raw::c_int, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleWrapper_InnerDoubleWrapper { + pub _address: u8, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleWrapper_InnerDoubleWrapper", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of OuterDoubleWrapper_InnerDoubleWrapper", + ][::std::mem::align_of::() - 1usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleWrapper", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of OuterDoubleWrapper", + ][::std::mem::align_of::() - 1usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleWrapper_InnerDoubleWrapper_sentry { + pub i_am_double_wrapper_sentry: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleWrapper_InnerDoubleWrapper_sentry", + ][::std::mem::size_of::() + - 4usize]; + [ + "Alignment of OuterDoubleWrapper_InnerDoubleWrapper_sentry", + ][::std::mem::align_of::() + - 4usize]; + [ + "Offset of field: OuterDoubleWrapper_InnerDoubleWrapper_sentry::i_am_double_wrapper_sentry", + ][::std::mem::offset_of!( + OuterDoubleWrapper_InnerDoubleWrapper_sentry, i_am_double_wrapper_sentry + ) - 0usize]; + }; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleInlineWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleInlineWrapper_InnerDoubleInlineWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry { + pub i_am_double_wrapper_inline_sentry: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry", + ][::std::mem::size_of::< + OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry, + >() - 4usize]; + [ + "Alignment of OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry", + ][::std::mem::align_of::< + OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry, + >() - 4usize]; + [ + "Offset of field: OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry::i_am_double_wrapper_inline_sentry", + ][::std::mem::offset_of!( + OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry, + i_am_double_wrapper_inline_sentry + ) - 0usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleInlineWrapper_InnerDoubleInlineWrapper", + ][::std::mem::size_of::() + - 1usize]; + [ + "Alignment of OuterDoubleInlineWrapper_InnerDoubleInlineWrapper", + ][::std::mem::align_of::() + - 1usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of OuterDoubleInlineWrapper", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of OuterDoubleInlineWrapper", + ][::std::mem::align_of::() - 1usize]; + }; + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OutsideNamespaceWrapper { + pub _address: u8, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct OutsideNamespaceWrapper_sentry { + pub i_am_outside_namespace_wrapper_sentry: ::std::os::raw::c_int, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct sentry { + pub i_am_outside_namespace_sentry: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of sentry"][::std::mem::size_of::() - 4usize]; + ["Alignment of sentry"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: sentry::i_am_outside_namespace_sentry", + ][::std::mem::offset_of!(sentry, i_am_outside_namespace_sentry) - 0usize]; + }; +} diff --git a/bindgen-tests/tests/expectations/tests/short-enums.rs b/bindgen-tests/tests/expectations/tests/short-enums.rs new file mode 100644 index 0000000000..493bb5b419 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/short-enums.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum one_byte_t { + SOME_VALUE = 1, +} +#[repr(u16)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum two_byte_t { + SOME_OTHER_VALUE = 256, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum four_byte_t { + SOME_BIGGER_VALUE = 16777216, +} diff --git a/bindgen-tests/tests/expectations/tests/size_t_template.rs b/bindgen-tests/tests/expectations/tests/size_t_template.rs new file mode 100644 index 0000000000..08ffa22750 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/size_t_template.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub T); +impl Default for __BindgenOpaqueArray<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct C { + pub arr: __BindgenOpaqueArray<[u32; 3usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 12usize]; + ["Alignment of C"][::std::mem::align_of::() - 4usize]; + ["Offset of field: C::arr"][::std::mem::offset_of!(C, arr) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/sort-items.rs b/bindgen-tests/tests/expectations/tests/sort-items.rs new file mode 100644 index 0000000000..e04e3b6090 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/sort-items.rs @@ -0,0 +1,220 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + pub type number = ::std::os::raw::c_int; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: root::number, + pub y: root::number, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Angle { + pub a: root::number, + pub b: root::number, + } + pub const NUMBER: root::number = 42; + #[test] + fn bindgen_test_layout_Point() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Point)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(Point)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(Point), + "::", + stringify!(x) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(Point), + "::", + stringify!(y) + ) + ); + } + #[test] + fn bindgen_test_layout_Angle() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Angle)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(Angle)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(Angle), + "::", + stringify!(a) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(Angle), + "::", + stringify!(b) + ) + ); + } + pub mod ns { + pub type number = ::std::os::raw::c_int; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: root::ns::number, + pub y: root::ns::number, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Angle { + pub a: root::ns::number, + pub b: root::ns::number, + } + pub const NUMBER: root::ns::number = 42; + #[test] + fn bindgen_test_layout_Point() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Point)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(Point)) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(Point), + "::", + stringify!(x) + ) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(Point), + "::", + stringify!(y) + ) + ); + } + #[test] + fn bindgen_test_layout_Angle() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Angle)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(Angle)) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(Angle), + "::", + stringify!(a) + ) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(Angle), + "::", + stringify!(b) + ) + ); + } + #[allow(unused_imports)] + use self::super::super::root; + extern "C" { + #[link_name = "\u{1}_ZN2ns3fooEv"] + pub fn foo() -> ::std::os::raw::c_int; + } + extern "C" { + #[link_name = "\u{1}_ZN2ns3barEi"] + pub fn bar(x: root::ns::number) -> ::std::os::raw::c_int; + } + extern "C" { + #[link_name = "\u{1}_ZN2ns3bazENS_5PointE"] + pub fn baz(point: root::ns::Point) -> ::std::os::raw::c_int; + } + } + #[allow(unused_imports)] + use self::super::root; + extern "C" { + #[link_name = "\u{1}_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; + } + extern "C" { + #[link_name = "\u{1}_Z3bari"] + pub fn bar(x: root::number) -> ::std::os::raw::c_int; + } + extern "C" { + #[link_name = "\u{1}_Z3baz5Point"] + pub fn baz(point: root::Point) -> ::std::os::raw::c_int; + } +} diff --git a/bindgen-tests/tests/expectations/tests/sorted_items.rs b/bindgen-tests/tests/expectations/tests/sorted_items.rs new file mode 100644 index 0000000000..1c235fb31d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/sorted_items.rs @@ -0,0 +1,90 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + pub type number = ::std::os::raw::c_int; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: root::number, + pub y: root::number, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Angle { + pub a: root::number, + pub b: root::number, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 8usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + ["Offset of field: Point::y"][::std::mem::offset_of!(Point, y) - 4usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Angle"][::std::mem::size_of::() - 8usize]; + ["Alignment of Angle"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Angle::a"][::std::mem::offset_of!(Angle, a) - 0usize]; + ["Offset of field: Angle::b"][::std::mem::offset_of!(Angle, b) - 4usize]; + }; + pub const NUMBER: root::number = 42; + pub mod ns { + pub type number = ::std::os::raw::c_int; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Point { + pub x: root::ns::number, + pub y: root::ns::number, + } + #[repr(C)] + #[derive(Debug, Default, Copy, Clone)] + pub struct Angle { + pub a: root::ns::number, + pub b: root::ns::number, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Point"][::std::mem::size_of::() - 8usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + ["Offset of field: Point::y"][::std::mem::offset_of!(Point, y) - 4usize]; + }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of Angle"][::std::mem::size_of::() - 8usize]; + ["Alignment of Angle"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Angle::a"][::std::mem::offset_of!(Angle, a) - 0usize]; + ["Offset of field: Angle::b"][::std::mem::offset_of!(Angle, b) - 4usize]; + }; + pub const NUMBER: root::ns::number = 42; + #[allow(unused_imports)] + use self::super::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_ZN2ns3fooEv"] + pub fn foo() -> ::std::os::raw::c_int; + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN2ns3barEi"] + pub fn bar(x: root::ns::number) -> ::std::os::raw::c_int; + } + unsafe extern "C" { + #[link_name = "\u{1}_ZN2ns3bazENS_5PointE"] + pub fn baz(point: root::ns::Point) -> ::std::os::raw::c_int; + } + } + #[allow(unused_imports)] + use self::super::root; + unsafe extern "C" { + #[link_name = "\u{1}_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; + } + unsafe extern "C" { + #[link_name = "\u{1}_Z3bari"] + pub fn bar(x: root::number) -> ::std::os::raw::c_int; + } + unsafe extern "C" { + #[link_name = "\u{1}_Z3baz5Point"] + pub fn baz(point: root::Point) -> ::std::os::raw::c_int; + } +} diff --git a/bindgen-tests/tests/expectations/tests/special-members.rs b/bindgen-tests/tests/expectations/tests/special-members.rs new file mode 100644 index 0000000000..4f54670c86 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/special-members.rs @@ -0,0 +1,51 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct A { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 1usize]; + ["Alignment of A"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN1AC1Ev"] + pub fn A_A(this: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1AC1ERS_"] + pub fn A_A1(this: *mut A, arg1: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1AC1EOS_"] + pub fn A_A2(this: *mut A, arg1: *mut A); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1AD1Ev"] + pub fn A_A_destructor(this: *mut A); +} +impl A { + #[inline] + pub unsafe fn new() -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + A_A(__bindgen_tmp.as_mut_ptr()); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn new1(arg1: *mut A) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + A_A1(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn new2(arg1: *mut A) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + A_A2(__bindgen_tmp.as_mut_ptr(), arg1); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn destruct(&mut self) { + A_A_destructor(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/specific_receiver.rs b/bindgen-tests/tests/expectations/tests/specific_receiver.rs new file mode 100644 index 0000000000..ec001b12ad --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/specific_receiver.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct Fish__bindgen_vtable { + pub Fish_swim: unsafe extern "C" fn(this: *mut Fish), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Fish { + pub vtable_: *const Fish__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Fish"][::std::mem::size_of::() - 8usize]; + ["Alignment of Fish"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Fish { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Fish4swimEv"] + pub fn Fish_swim(this: *mut Fish); +} diff --git a/bindgen-tests/tests/expectations/tests/stdint_typedef.rs b/bindgen-tests/tests/expectations/tests/stdint_typedef.rs new file mode 100644 index 0000000000..7cb1a2a8fb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/stdint_typedef.rs @@ -0,0 +1,15 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn fun() -> u64; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Struct { + pub field: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Struct"][::std::mem::size_of::() - 8usize]; + ["Alignment of Struct"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Struct::field"][::std::mem::offset_of!(Struct, field) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/strings_array.rs b/bindgen-tests/tests/expectations/tests/strings_array.rs new file mode 100644 index 0000000000..12543e59a8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/strings_array.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const MY_STRING_UTF8: &[u8; 14] = b"Hello, world!\0"; +pub const MY_STRING_INTERIOR_NULL: &[u8; 7] = b"Hello,\0"; +pub const MY_STRING_NON_UTF8: &[u8; 7] = b"ABCDE\xFF\0"; diff --git a/bindgen-tests/tests/expectations/tests/strings_cstr.rs b/bindgen-tests/tests/expectations/tests/strings_cstr.rs new file mode 100644 index 0000000000..ca089cf130 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/strings_cstr.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(unsafe_code)] +pub const MY_STRING_UTF8: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0") +}; +#[allow(unsafe_code)] +pub const MY_STRING_INTERIOR_NULL: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"Hello,\0") +}; +#[allow(unsafe_code)] +pub const MY_STRING_NON_UTF8: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"ABCDE\xFF\0") +}; diff --git a/bindgen-tests/tests/expectations/tests/strings_cstr2.rs b/bindgen-tests/tests/expectations/tests/strings_cstr2.rs new file mode 100644 index 0000000000..2ce21f4374 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/strings_cstr2.rs @@ -0,0 +1,4 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const MY_STRING_UTF8: &::std::ffi::CStr = c"Hello, world!"; +pub const MY_STRING_INTERIOR_NULL: &::std::ffi::CStr = c"Hello,"; +pub const MY_STRING_NON_UTF8: &::std::ffi::CStr = c"ABCDE\xFF"; diff --git a/bindgen-tests/tests/expectations/tests/strings_cstr2_2018.rs b/bindgen-tests/tests/expectations/tests/strings_cstr2_2018.rs new file mode 100644 index 0000000000..ca089cf130 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/strings_cstr2_2018.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(unsafe_code)] +pub const MY_STRING_UTF8: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0") +}; +#[allow(unsafe_code)] +pub const MY_STRING_INTERIOR_NULL: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"Hello,\0") +}; +#[allow(unsafe_code)] +pub const MY_STRING_NON_UTF8: &::std::ffi::CStr = unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"ABCDE\xFF\0") +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_containing_forward_declared_struct.rs b/bindgen-tests/tests/expectations/tests/struct_containing_forward_declared_struct.rs new file mode 100644 index 0000000000..0fe9024a5f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_containing_forward_declared_struct.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct a { + pub val_a: *mut b, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of a"][::std::mem::size_of::() - 8usize]; + ["Alignment of a"][::std::mem::align_of::() - 8usize]; + ["Offset of field: a::val_a"][::std::mem::offset_of!(a, val_a) - 0usize]; +}; +impl Default for a { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct b { + pub val_b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of b"][::std::mem::size_of::() - 4usize]; + ["Alignment of b"][::std::mem::align_of::() - 4usize]; + ["Offset of field: b::val_b"][::std::mem::offset_of!(b, val_b) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_typedef.rs b/bindgen-tests/tests/expectations/tests/struct_typedef.rs new file mode 100644 index 0000000000..bc12a1bce8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_typedef.rs @@ -0,0 +1,55 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct typedef_named_struct { + pub has_name: bool, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of typedef_named_struct", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of typedef_named_struct", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: typedef_named_struct::has_name", + ][::std::mem::offset_of!(typedef_named_struct, has_name) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct _bindgen_ty_1 { + pub no_name: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 8usize]; + ["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 8usize]; + [ + "Offset of field: _bindgen_ty_1::no_name", + ][::std::mem::offset_of!(_bindgen_ty_1, no_name) - 0usize]; +}; +impl Default for _bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type struct_ptr_t = *mut _bindgen_ty_1; +pub type struct_ptr_ptr_t = *mut *mut _bindgen_ty_1; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum typedef_named_enum { + ENUM_HAS_NAME = 1, +} +pub const ENUM_IS_ANON: _bindgen_ty_2 = _bindgen_ty_2::ENUM_IS_ANON; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum _bindgen_ty_2 { + ENUM_IS_ANON = 0, +} +pub type enum_ptr_t = *mut _bindgen_ty_2; +pub type enum_ptr_ptr_t = *mut *mut _bindgen_ty_2; diff --git a/bindgen-tests/tests/expectations/tests/struct_typedef_ns.rs b/bindgen-tests/tests/expectations/tests/struct_typedef_ns.rs new file mode 100644 index 0000000000..82f93dfd16 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_typedef_ns.rs @@ -0,0 +1,54 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod whatever { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct typedef_struct { + pub foo: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of typedef_struct"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of typedef_struct", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: typedef_struct::foo", + ][::std::mem::offset_of!(typedef_struct, foo) - 0usize]; + }; + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum typedef_enum { + BAR = 1, + } + } + pub mod _bindgen_mod_id_12 { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] + pub struct typedef_struct { + pub foo: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of typedef_struct"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of typedef_struct", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: typedef_struct::foo", + ][::std::mem::offset_of!(typedef_struct, foo) - 0usize]; + }; + #[repr(u32)] + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub enum typedef_enum { + BAR = 1, + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_struct.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct.rs new file mode 100644 index 0000000000..51aa19c572 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_array.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_array.rs new file mode 100644 index 0000000000..930e6b9aba --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_array.rs @@ -0,0 +1,52 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub bar: [foo__bindgen_ty_1; 2usize], + pub baz: [[[foo__bindgen_ty_2; 4usize]; 3usize]; 2usize], +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_2 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_2"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_2", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_2::a", + ][::std::mem::offset_of!(foo__bindgen_ty_2, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_2::b", + ][::std::mem::offset_of!(foo__bindgen_ty_2, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 208usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; + ["Offset of field: foo::baz"][::std::mem::offset_of!(foo, baz) - 16usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_pointer.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_pointer.rs new file mode 100644 index 0000000000..6bdee34590 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_struct_pointer.rs @@ -0,0 +1,40 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub bar: *mut foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_union.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_union.rs new file mode 100644 index 0000000000..6520163259 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_union.rs @@ -0,0 +1,49 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_struct.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_struct.rs new file mode 100644 index 0000000000..29cf382e5f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_struct.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_union.rs b/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_union.rs new file mode 100644 index 0000000000..2f95e0f5e0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_anon_unnamed_union.rs @@ -0,0 +1,48 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo { + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs b/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs new file mode 100644 index 0000000000..a294c871d3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs @@ -0,0 +1,450 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct bitfield { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub e: ::std::os::raw::c_int, + pub _bitfield_2: __BindgenBitfieldUnit<[u8; 8usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bitfield"][::std::mem::size_of::() - 16usize]; + ["Alignment of bitfield"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bitfield::e"][::std::mem::offset_of!(bitfield, e) - 4usize]; +}; +impl bitfield { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 1usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 1usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn c(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn c_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 2usize, 1u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_c_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 2usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn d(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 2u8) as u16) } + } + #[inline] + pub fn set_d(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(6usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn d_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 6usize, 2u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_d_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 6usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + a: ::std::os::raw::c_ushort, + b: ::std::os::raw::c_ushort, + c: ::std::os::raw::c_ushort, + d: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let a: u16 = unsafe { ::std::mem::transmute(a) }; + a as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 1usize, + 1u8, + { + let b: u16 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 2usize, + 1u8, + { + let c: u16 = unsafe { ::std::mem::transmute(c) }; + c as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 2u8, + { + let d: u16 = unsafe { ::std::mem::transmute(d) }; + d as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub fn f(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 2u8) as u32) } + } + #[inline] + pub fn set_f(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_2.set(0usize, 2u8, val as u64) + } + } + #[inline] + pub unsafe fn f_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 0usize, 2u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_f_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 0usize, + 2u8, + val as u64, + ) + } + } + #[inline] + pub fn g(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_2.get(32usize, 32u8) as u32) } + } + #[inline] + pub fn set_g(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_2.set(32usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn g_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 32usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_g_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 8usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 32usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_2( + f: ::std::os::raw::c_uint, + g: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 2u8, + { + let f: u32 = unsafe { ::std::mem::transmute(f) }; + f as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 32usize, + 32u8, + { + let g: u32 = unsafe { ::std::mem::transmute(g) }; + g as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_derive_debug.rs b/bindgen-tests/tests/expectations/tests/struct_with_derive_debug.rs new file mode 100644 index 0000000000..f86fe6fb8f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_derive_debug.rs @@ -0,0 +1,67 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct LittleArray { + pub a: [::std::os::raw::c_int; 32usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of LittleArray"][::std::mem::size_of::() - 128usize]; + ["Alignment of LittleArray"][::std::mem::align_of::() - 4usize]; + ["Offset of field: LittleArray::a"][::std::mem::offset_of!(LittleArray, a) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct BigArray { + pub a: [::std::os::raw::c_int; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of BigArray"][::std::mem::size_of::() - 132usize]; + ["Alignment of BigArray"][::std::mem::align_of::() - 4usize]; + ["Offset of field: BigArray::a"][::std::mem::offset_of!(BigArray, a) - 0usize]; +}; +impl Default for BigArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct WithLittleArray { + pub a: LittleArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithLittleArray"][::std::mem::size_of::() - 128usize]; + ["Alignment of WithLittleArray"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithLittleArray::a", + ][::std::mem::offset_of!(WithLittleArray, a) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct WithBigArray { + pub a: BigArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithBigArray"][::std::mem::size_of::() - 132usize]; + ["Alignment of WithBigArray"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithBigArray::a", + ][::std::mem::offset_of!(WithBigArray, a) - 0usize]; +}; +impl Default for WithBigArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_large_array.rs b/bindgen-tests/tests/expectations/tests/struct_with_large_array.rs new file mode 100644 index 0000000000..df7a2192ed --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_large_array.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct S { + pub large_array: [::std::os::raw::c_char; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S"][::std::mem::size_of::() - 33usize]; + ["Alignment of S"][::std::mem::align_of::() - 1usize]; + ["Offset of field: S::large_array"][::std::mem::offset_of!(S, large_array) - 0usize]; +}; +impl Default for S { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ST { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub large_array: [T; 33usize], +} +impl Default for ST { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_nesting.rs b/bindgen-tests/tests/expectations/tests/struct_with_nesting.rs new file mode 100644 index 0000000000..369384e88c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_nesting.rs @@ -0,0 +1,98 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo { + pub a: ::std::os::raw::c_uint, + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub b: ::std::os::raw::c_uint, + pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, + pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1__bindgen_ty_1 { + pub c1: ::std::os::raw::c_ushort, + pub c2: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of foo__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_1::c1", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_1, c1) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_1::c2", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_1, c2) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1__bindgen_ty_2 { + pub d1: ::std::os::raw::c_uchar, + pub d2: ::std::os::raw::c_uchar, + pub d3: ::std::os::raw::c_uchar, + pub d4: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of foo__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::d1", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, d1) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::d2", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, d2) - 1usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::d3", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, d3) - 2usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::d4", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, d4) - 3usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::a"][::std::mem::offset_of!(foo, a) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/struct_with_packing.rs b/bindgen-tests/tests/expectations/tests/struct_with_packing.rs new file mode 100644 index 0000000000..2687f9750b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_packing.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct a { + pub b: ::std::os::raw::c_char, + pub c: ::std::os::raw::c_short, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of a"][::std::mem::size_of::() - 3usize]; + ["Alignment of a"][::std::mem::align_of::() - 1usize]; + ["Offset of field: a::b"][::std::mem::offset_of!(a, b) - 0usize]; + ["Offset of field: a::c"][::std::mem::offset_of!(a, c) - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/struct_with_struct.rs b/bindgen-tests/tests/expectations/tests/struct_with_struct.rs new file mode 100644 index 0000000000..40c3972600 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/struct_with_struct.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub x: ::std::os::raw::c_uint, + pub y: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::x", + ][::std::mem::offset_of!(foo__bindgen_ty_1, x) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::y", + ][::std::mem::offset_of!(foo__bindgen_ty_1, y) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; diff --git a/tests/expectations/tests/struct_with_typedef_template_arg.rs b/bindgen-tests/tests/expectations/tests/struct_with_typedef_template_arg.rs similarity index 84% rename from tests/expectations/tests/struct_with_typedef_template_arg.rs rename to bindgen-tests/tests/expectations/tests/struct_with_typedef_template_arg.rs index 2c21656ad6..2aaae12dcf 100644 --- a/tests/expectations/tests/struct_with_typedef_template_arg.rs +++ b/bindgen-tests/tests/expectations/tests/struct_with_typedef_template_arg.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct Proxy { diff --git a/tests/expectations/tests/template-fun-ty.rs b/bindgen-tests/tests/expectations/tests/template-fun-ty.rs similarity index 93% rename from tests/expectations/tests/template-fun-ty.rs rename to bindgen-tests/tests/expectations/tests/template-fun-ty.rs index cce6c24d3c..5337af037a 100644 --- a/tests/expectations/tests/template-fun-ty.rs +++ b/bindgen-tests/tests/expectations/tests/template-fun-ty.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct Foo { diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-0.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-0.rs new file mode 100644 index 0000000000..ba8980be00 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-0.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +impl Default for UsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/template-param-usage-1.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-1.rs similarity index 80% rename from tests/expectations/tests/template-param-usage-1.rs rename to bindgen-tests/tests/expectations/tests/template-param-usage-1.rs index 95e41077b5..7cbec9610d 100644 --- a/tests/expectations/tests/template-param-usage-1.rs +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-1.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct DoesNotUseTemplateParameter { diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-10.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-10.rs new file mode 100644 index 0000000000..a4e5d0ce82 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-10.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DoublyIndirectUsage { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub doubly_indirect: DoublyIndirectUsage_IndirectUsage, +} +pub type DoublyIndirectUsage_Aliased = T; +pub type DoublyIndirectUsage_Typedefed = U; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DoublyIndirectUsage_IndirectUsage { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: DoublyIndirectUsage_Aliased, + pub another: DoublyIndirectUsage_Typedefed, +} +impl Default for DoublyIndirectUsage_IndirectUsage { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for DoublyIndirectUsage { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/template-param-usage-11.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-11.rs similarity index 78% rename from tests/expectations/tests/template-param-usage-11.rs rename to bindgen-tests/tests/expectations/tests/template-param-usage-11.rs index 1b2335bb1e..e914375875 100644 --- a/tests/expectations/tests/template-param-usage-11.rs +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-11.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct DoesNotUseT { diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-12.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-12.rs new file mode 100644 index 0000000000..7f3a306b6b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-12.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct BaseUsesT { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: *mut T, +} +impl Default for BaseUsesT { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CrtpUsesU { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: BaseUsesT>, + pub usage: U, +} +impl Default for CrtpUsesU { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-13.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-13.rs new file mode 100644 index 0000000000..185f16be11 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-13.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct BaseIgnoresT { + pub x: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CrtpUsesU { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _base: BaseIgnoresT, + pub usage: U, +} +impl Default for CrtpUsesU { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-14.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-14.rs new file mode 100644 index 0000000000..b008bb5b8f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-14.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct BaseIgnoresT { + pub x: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CrtpIgnoresU { + pub _base: BaseIgnoresT, + pub y: ::std::os::raw::c_int, +} +impl Default for CrtpIgnoresU { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-15.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-15.rs new file mode 100644 index 0000000000..fced6dc58c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-15.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct BaseUsesT { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub usage: *mut T, +} +impl Default for BaseUsesT { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CrtpIgnoresU { + pub _base: BaseUsesT, + pub y: ::std::os::raw::c_int, +} +impl Default for CrtpIgnoresU { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-2.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-2.rs new file mode 100644 index 0000000000..4c671ce2ab --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-2.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter_AlsoUsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub also: T, +} +impl Default for UsesTemplateParameter_AlsoUsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for UsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-3.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-3.rs new file mode 100644 index 0000000000..511365e656 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-3.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter_AlsoUsesTemplateParameterAndMore { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub also: T, + pub more: U, +} +impl Default for UsesTemplateParameter_AlsoUsesTemplateParameterAndMore { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for UsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-4.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-4.rs new file mode 100644 index 0000000000..5655a6d260 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-4.rs @@ -0,0 +1,21 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct UsesTemplateParameter_DoesNotUseTemplateParameters { + pub x: ::std::os::raw::c_int, +} +impl Default for UsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-5.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-5.rs new file mode 100644 index 0000000000..5049559b33 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-5.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct IndirectlyUsesTemplateParameter { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub aliased: IndirectlyUsesTemplateParameter_Aliased, +} +pub type IndirectlyUsesTemplateParameter_Aliased = T; +impl Default for IndirectlyUsesTemplateParameter { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/template-param-usage-6.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-6.rs similarity index 84% rename from tests/expectations/tests/template-param-usage-6.rs rename to bindgen-tests/tests/expectations/tests/template-param-usage-6.rs index f76e6326e6..0a08bc9da9 100644 --- a/tests/expectations/tests/template-param-usage-6.rs +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-6.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct DoesNotUseTemplateParameter { diff --git a/bindgen-tests/tests/expectations/tests/template-param-usage-7.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-7.rs new file mode 100644 index 0000000000..1552ae852f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-7.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DoesNotUseU { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, + pub v: V, +} +impl Default for DoesNotUseU { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type Alias = DoesNotUseU<::std::os::raw::c_int, ::std::os::raw::c_char>; diff --git a/tests/expectations/tests/template-param-usage-8.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-8.rs similarity index 75% rename from tests/expectations/tests/template-param-usage-8.rs rename to bindgen-tests/tests/expectations/tests/template-param-usage-8.rs index 75e14706f5..61de18a833 100644 --- a/tests/expectations/tests/template-param-usage-8.rs +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-8.rs @@ -1,21 +1,20 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct IndirectUsage { - pub member1: IndirectUsage_Typedefed, - pub member2: IndirectUsage_Aliased, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member1: IndirectUsage_Typedefed, + pub member2: IndirectUsage_Aliased, } pub type IndirectUsage_Typedefed = T; pub type IndirectUsage_Aliased = U; impl Default for IndirectUsage { fn default() -> Self { - unsafe { ::std::mem::zeroed() } + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } } } diff --git a/tests/expectations/tests/template-param-usage-9.rs b/bindgen-tests/tests/expectations/tests/template-param-usage-9.rs similarity index 79% rename from tests/expectations/tests/template-param-usage-9.rs rename to bindgen-tests/tests/expectations/tests/template-param-usage-9.rs index 3071924e49..ff0eedc8ae 100644 --- a/tests/expectations/tests/template-param-usage-9.rs +++ b/bindgen-tests/tests/expectations/tests/template-param-usage-9.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct DoesNotUse { @@ -14,13 +9,17 @@ pub type DoesNotUse_Typedefed = U; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct DoesNotUse_IndirectUsage { - pub member: DoesNotUse_Aliased, - pub another: DoesNotUse_Typedefed, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: DoesNotUse_Aliased, + pub another: DoesNotUse_Typedefed, } impl Default for DoesNotUse_IndirectUsage { fn default() -> Self { - unsafe { ::std::mem::zeroed() } + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } } } diff --git a/tests/expectations/tests/template-with-var.rs b/bindgen-tests/tests/expectations/tests/template-with-var.rs similarity index 78% rename from tests/expectations/tests/template-with-var.rs rename to bindgen-tests/tests/expectations/tests/template-with-var.rs index 0b0a8cb6b2..cdc0b5b149 100644 --- a/tests/expectations/tests/template-with-var.rs +++ b/bindgen-tests/tests/expectations/tests/template-with-var.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct TemplateWithVar { diff --git a/bindgen-tests/tests/expectations/tests/template.rs b/bindgen-tests/tests/expectations/tests/template.rs new file mode 100644 index 0000000000..94678cb49e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template.rs @@ -0,0 +1,566 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct Foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_member: T, + pub m_member_ptr: *mut T, + pub m_member_arr: [T; 1usize], +} +impl Default for Foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct B { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_member: T, +} +impl Default for B { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_Z3bar3FooIiiE"] + pub fn bar(foo: Foo<::std::os::raw::c_int>); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct mozilla_Foo { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct C { + pub mB: B<::std::os::raw::c_uint>, + pub mBConstPtr: B<*const ::std::os::raw::c_int>, + pub mBConstStructPtr: B<*const mozilla_Foo>, + pub mBConstStructPtrArray: B<[*const mozilla_Foo; 1usize]>, + pub mBConst: B<::std::os::raw::c_int>, + pub mBVolatile: B<::std::os::raw::c_int>, + pub mBConstBool: B, + pub mBConstChar: B, + pub mBArray: B<[::std::os::raw::c_int; 1usize]>, + pub mBPtrArray: B<[*mut ::std::os::raw::c_int; 1usize]>, + pub mBArrayPtr: B<*mut [::std::os::raw::c_int; 1usize]>, + pub mBRef: B<*mut ::std::os::raw::c_int>, + pub mBConstRef: B<*const ::std::os::raw::c_int>, + pub mPtrRef: B<*mut *mut ::std::os::raw::c_int>, + pub mArrayRef: B<*mut [::std::os::raw::c_int; 1usize]>, + pub mBConstArray: B<[::std::os::raw::c_int; 1usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 104usize]; + ["Alignment of C"][::std::mem::align_of::() - 8usize]; + ["Offset of field: C::mB"][::std::mem::offset_of!(C, mB) - 0usize]; + ["Offset of field: C::mBConstPtr"][::std::mem::offset_of!(C, mBConstPtr) - 8usize]; + [ + "Offset of field: C::mBConstStructPtr", + ][::std::mem::offset_of!(C, mBConstStructPtr) - 16usize]; + [ + "Offset of field: C::mBConstStructPtrArray", + ][::std::mem::offset_of!(C, mBConstStructPtrArray) - 24usize]; + ["Offset of field: C::mBConst"][::std::mem::offset_of!(C, mBConst) - 32usize]; + ["Offset of field: C::mBVolatile"][::std::mem::offset_of!(C, mBVolatile) - 36usize]; + [ + "Offset of field: C::mBConstBool", + ][::std::mem::offset_of!(C, mBConstBool) - 40usize]; + [ + "Offset of field: C::mBConstChar", + ][::std::mem::offset_of!(C, mBConstChar) - 42usize]; + ["Offset of field: C::mBArray"][::std::mem::offset_of!(C, mBArray) - 44usize]; + ["Offset of field: C::mBPtrArray"][::std::mem::offset_of!(C, mBPtrArray) - 48usize]; + ["Offset of field: C::mBArrayPtr"][::std::mem::offset_of!(C, mBArrayPtr) - 56usize]; + ["Offset of field: C::mBRef"][::std::mem::offset_of!(C, mBRef) - 64usize]; + ["Offset of field: C::mBConstRef"][::std::mem::offset_of!(C, mBConstRef) - 72usize]; + ["Offset of field: C::mPtrRef"][::std::mem::offset_of!(C, mPtrRef) - 80usize]; + ["Offset of field: C::mArrayRef"][::std::mem::offset_of!(C, mArrayRef) - 88usize]; + [ + "Offset of field: C::mBConstArray", + ][::std::mem::offset_of!(C, mBConstArray) - 96usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct D { + pub m_foo: D_MyFoo, +} +pub type D_MyFoo = Foo<::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct D_U { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_nested_foo: D_MyFoo, + pub m_baz: Z, +} +impl Default for D_U { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for D { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub prev: *mut T, + pub next: *mut Rooted<*mut ::std::os::raw::c_void>, + pub ptr: T, +} +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RootedContainer { + pub root: Rooted<*mut ::std::os::raw::c_void>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of RootedContainer"][::std::mem::size_of::() - 24usize]; + ["Alignment of RootedContainer"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: RootedContainer::root", + ][::std::mem::offset_of!(RootedContainer, root) - 0usize]; +}; +impl Default for RootedContainer { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct WithDtor { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, +} +impl Default for WithDtor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct PODButContainsDtor { + pub member: WithDtorIntFwd, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PODButContainsDtor"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of PODButContainsDtor", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: PODButContainsDtor::member", + ][::std::mem::offset_of!(PODButContainsDtor, member) - 0usize]; +}; +impl Default for PODButContainsDtor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Opaque { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct POD { + pub opaque_member: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of POD"][::std::mem::size_of::() - 4usize]; + ["Alignment of POD"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: POD::opaque_member", + ][::std::mem::offset_of!(POD, opaque_member) - 0usize]; +}; +///
+#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct NestedReplaced { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub buff: *mut T, +} +impl Default for NestedReplaced { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct NestedBase { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub buff: *mut T, +} +impl Default for NestedBase { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct NestedContainer { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub c: T, + pub nested: NestedReplaced, + pub inc: Incomplete, +} +impl Default for NestedContainer { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Incomplete { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub d: T, +} +impl Default for Incomplete { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Untemplated { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Untemplated"][::std::mem::size_of::() - 1usize]; + ["Alignment of Untemplated"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Templated { + pub m_untemplated: Untemplated, +} +/** If the replacement doesn't happen at the parse level the container would be + copy and the replacement wouldn't, so this wouldn't compile. + +
*/ +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ReplacedWithoutDestructor { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub buff: *mut T, +} +impl Default for ReplacedWithoutDestructor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ShouldNotBeCopiable { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_member: ReplacedWithoutDestructor, +} +impl Default for ShouldNotBeCopiable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ShouldNotBeCopiableAsWell { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub m_member: ReplacedWithoutDestructorFwd, +} +impl Default for ShouldNotBeCopiableAsWell { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +/** If the replacement doesn't happen at the parse level the container would be + copy and the replacement wouldn't, so this wouldn't compile. + +
*/ +#[repr(C)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ReplacedWithoutDestructorFwd { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub buff: *mut T, +} +impl Default for ReplacedWithoutDestructorFwd { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Foo_open0_int_int_close0", + ][::std::mem::size_of::>() - 24usize]; + [ + "Align of template specialization: Foo_open0_int_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_unsigned_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: B_open0_unsigned_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ptr_const_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ptr_const_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ptr_const_mozilla__Foo_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ptr_const_mozilla__Foo_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_array1_ptr_const_mozilla__Foo_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_array1_ptr_const_mozilla__Foo_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_const_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: B_open0_const_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_volatile_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: B_open0_volatile_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_const_bool_close0", + ][::std::mem::size_of::>() - 1usize]; + [ + "Align of template specialization: B_open0_const_bool_close0", + ][::std::mem::align_of::>() - 1usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_const_char16_t_close0", + ][::std::mem::size_of::>() - 2usize]; + [ + "Align of template specialization: B_open0_const_char16_t_close0", + ][::std::mem::align_of::>() - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_array1_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: B_open0_array1_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_array1_ptr_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_array1_ptr_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ptr_array1_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ptr_array1_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ref_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ref_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ref_const_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ref_const_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ref_ptr_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ref_ptr_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_ref_array1_int_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: B_open0_ref_array1_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: B_open0_array1_const_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: B_open0_array1_const_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Foo_open0_int_int_close0", + ][::std::mem::size_of::>() - 24usize]; + [ + "Align of template specialization: Foo_open0_int_int_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Rooted_open0_ptr_void_close0", + ][::std::mem::size_of::>() - 24usize]; + [ + "Align of template specialization: Rooted_open0_ptr_void_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Rooted_open0_ptr_void_close0", + ][::std::mem::size_of::>() - 24usize]; + [ + "Align of template specialization: Rooted_open0_ptr_void_close0", + ][::std::mem::align_of::>() - 8usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: WithDtor_open0_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: WithDtor_open0_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/template_alias.rs b/bindgen-tests/tests/expectations/tests/template_alias.rs new file mode 100644 index 0000000000..b270c9f3a4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_alias.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type JS_detail_Wrapped = T; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct JS_Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: JS_detail_Wrapped, +} +impl Default for JS_Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/template_alias_basic.rs b/bindgen-tests/tests/expectations/tests/template_alias_basic.rs new file mode 100644 index 0000000000..d0f8f104c7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_alias_basic.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type Wrapped = T; diff --git a/tests/expectations/tests/template_alias_namespace.rs b/bindgen-tests/tests/expectations/tests/template_alias_namespace.rs similarity index 79% rename from tests/expectations/tests/template_alias_namespace.rs rename to bindgen-tests/tests/expectations/tests/template_alias_namespace.rs index dc03a23173..0aa5fc679a 100644 --- a/tests/expectations/tests/template_alias_namespace.rs +++ b/bindgen-tests/tests/expectations/tests/template_alias_namespace.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] pub mod root { #[allow(unused_imports)] @@ -19,12 +14,16 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rooted { - pub ptr: root::JS::detail::Wrapped, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: root::JS::detail::Wrapped, } impl Default for Rooted { fn default() -> Self { - unsafe { ::std::mem::zeroed() } + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } } } } diff --git a/bindgen-tests/tests/expectations/tests/template_fun.rs b/bindgen-tests/tests/expectations/tests/template_fun.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_fun.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/template_instantiation_with_fn_local_type.rs b/bindgen-tests/tests/expectations/tests/template_instantiation_with_fn_local_type.rs new file mode 100644 index 0000000000..085278e603 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_instantiation_with_fn_local_type.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_Z1fv"] + pub fn f(); +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Foo_open0_Bar_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: Foo_open0_Bar_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 1usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 1usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: Foo_open0_Boo_close0", + ][::std::mem::size_of::() - 1usize]; + [ + "Align of template specialization: Foo_open0_Boo_close0", + ][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Boo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Boo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Boo"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/template_partial_specification.rs b/bindgen-tests/tests/expectations/tests/template_partial_specification.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_partial_specification.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/template_typedef_transitive_param.rs b/bindgen-tests/tests/expectations/tests/template_typedef_transitive_param.rs new file mode 100644 index 0000000000..2efdde944e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/template_typedef_transitive_param.rs @@ -0,0 +1,22 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Wrapper { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Wrapper_Wrapped { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub t: T, +} +impl Default for Wrapper_Wrapped { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type Wrapper_Type = Wrapper_Wrapped; diff --git a/tests/expectations/tests/template_typedefs.rs b/bindgen-tests/tests/expectations/tests/template_typedefs.rs similarity index 90% rename from tests/expectations/tests/template_typedefs.rs rename to bindgen-tests/tests/expectations/tests/template_typedefs.rs index df16f9f685..71f0732a63 100644 --- a/tests/expectations/tests/template_typedefs.rs +++ b/bindgen-tests/tests/expectations/tests/template_typedefs.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - pub type foo = ::std::option::Option; #[repr(C)] #[derive(Debug, Default, Copy, Clone)] diff --git a/tests/expectations/tests/templateref_opaque.rs b/bindgen-tests/tests/expectations/tests/templateref_opaque.rs similarity index 89% rename from tests/expectations/tests/templateref_opaque.rs rename to bindgen-tests/tests/expectations/tests/templateref_opaque.rs index 481a31bba6..8f73e86c31 100644 --- a/tests/expectations/tests/templateref_opaque.rs +++ b/bindgen-tests/tests/expectations/tests/templateref_opaque.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct detail_PointerType { diff --git a/bindgen-tests/tests/expectations/tests/templatized-bitfield.rs b/bindgen-tests/tests/expectations/tests/templatized-bitfield.rs new file mode 100644 index 0000000000..1b3e712361 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/templatized-bitfield.rs @@ -0,0 +1,9 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** We don't get a layout for this bitfield, since we don't know what `T` will + be, so we cannot allocate bitfield units. The best thing we can do is make + the struct opaque.*/ +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct TemplatizedBitfield { + pub _address: u8, +} diff --git a/bindgen-tests/tests/expectations/tests/test_macro_fallback_non_system_dir.rs b/bindgen-tests/tests/expectations/tests/test_macro_fallback_non_system_dir.rs new file mode 100644 index 0000000000..bf9739f3fa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/test_macro_fallback_non_system_dir.rs @@ -0,0 +1,6 @@ +pub const CONST: u32 = 5; +pub const OTHER_CONST: u32 = 6; +pub const LARGE_CONST: u32 = 1536; +pub const THE_CONST: u32 = 28; +pub const MY_CONST: u32 = 69; +pub const NEGATIVE: i32 = -1; diff --git a/bindgen-tests/tests/expectations/tests/test_mixed_header_and_header_contents.rs b/bindgen-tests/tests/expectations/tests/test_mixed_header_and_header_contents.rs new file mode 100644 index 0000000000..e1872623bc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/test_mixed_header_and_header_contents.rs @@ -0,0 +1,50 @@ +unsafe extern "C" { + pub static mut foo: ::std::option::Option< + unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >; +} +unsafe extern "C" { + pub fn bar(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn bar2(b: *const ::std::os::raw::c_char) -> f32; +} +pub type Char = ::std::os::raw::c_char; +pub type SChar = ::std::os::raw::c_schar; +pub type UChar = ::std::os::raw::c_uchar; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Test { + pub ch: ::std::os::raw::c_char, + pub u: ::std::os::raw::c_uchar, + pub d: ::std::os::raw::c_schar, + pub cch: ::std::os::raw::c_char, + pub cu: ::std::os::raw::c_uchar, + pub cd: ::std::os::raw::c_schar, + pub Cch: Char, + pub Cu: UChar, + pub Cd: SChar, + pub Ccch: Char, + pub Ccu: UChar, + pub Ccd: SChar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 12usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Test::ch"][::std::mem::offset_of!(Test, ch) - 0usize]; + ["Offset of field: Test::u"][::std::mem::offset_of!(Test, u) - 1usize]; + ["Offset of field: Test::d"][::std::mem::offset_of!(Test, d) - 2usize]; + ["Offset of field: Test::cch"][::std::mem::offset_of!(Test, cch) - 3usize]; + ["Offset of field: Test::cu"][::std::mem::offset_of!(Test, cu) - 4usize]; + ["Offset of field: Test::cd"][::std::mem::offset_of!(Test, cd) - 5usize]; + ["Offset of field: Test::Cch"][::std::mem::offset_of!(Test, Cch) - 6usize]; + ["Offset of field: Test::Cu"][::std::mem::offset_of!(Test, Cu) - 7usize]; + ["Offset of field: Test::Cd"][::std::mem::offset_of!(Test, Cd) - 8usize]; + ["Offset of field: Test::Ccch"][::std::mem::offset_of!(Test, Ccch) - 9usize]; + ["Offset of field: Test::Ccu"][::std::mem::offset_of!(Test, Ccu) - 10usize]; + ["Offset of field: Test::Ccd"][::std::mem::offset_of!(Test, Ccd) - 11usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/test_multiple_header_calls_in_builder.rs b/bindgen-tests/tests/expectations/tests/test_multiple_header_calls_in_builder.rs new file mode 100644 index 0000000000..2e62ac902f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/test_multiple_header_calls_in_builder.rs @@ -0,0 +1,44 @@ +unsafe extern "C" { + pub static mut foo: ::std::option::Option< + unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >; +} +pub type Char = ::std::os::raw::c_char; +pub type SChar = ::std::os::raw::c_schar; +pub type UChar = ::std::os::raw::c_uchar; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Test { + pub ch: ::std::os::raw::c_char, + pub u: ::std::os::raw::c_uchar, + pub d: ::std::os::raw::c_schar, + pub cch: ::std::os::raw::c_char, + pub cu: ::std::os::raw::c_uchar, + pub cd: ::std::os::raw::c_schar, + pub Cch: Char, + pub Cu: UChar, + pub Cd: SChar, + pub Ccch: Char, + pub Ccu: UChar, + pub Ccd: SChar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 12usize]; + ["Alignment of Test"][::std::mem::align_of::() - 1usize]; + ["Offset of field: Test::ch"][::std::mem::offset_of!(Test, ch) - 0usize]; + ["Offset of field: Test::u"][::std::mem::offset_of!(Test, u) - 1usize]; + ["Offset of field: Test::d"][::std::mem::offset_of!(Test, d) - 2usize]; + ["Offset of field: Test::cch"][::std::mem::offset_of!(Test, cch) - 3usize]; + ["Offset of field: Test::cu"][::std::mem::offset_of!(Test, cu) - 4usize]; + ["Offset of field: Test::cd"][::std::mem::offset_of!(Test, cd) - 5usize]; + ["Offset of field: Test::Cch"][::std::mem::offset_of!(Test, Cch) - 6usize]; + ["Offset of field: Test::Cu"][::std::mem::offset_of!(Test, Cu) - 7usize]; + ["Offset of field: Test::Cd"][::std::mem::offset_of!(Test, Cd) - 8usize]; + ["Offset of field: Test::Ccch"][::std::mem::offset_of!(Test, Ccch) - 9usize]; + ["Offset of field: Test::Ccu"][::std::mem::offset_of!(Test, Ccu) - 10usize]; + ["Offset of field: Test::Ccd"][::std::mem::offset_of!(Test, Ccd) - 11usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/timex.rs b/bindgen-tests/tests/expectations/tests/timex.rs new file mode 100644 index 0000000000..f73b608de2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/timex.rs @@ -0,0 +1,589 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct timex { + pub tai: ::std::os::raw::c_int, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 44usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of timex"][::std::mem::size_of::() - 48usize]; + ["Alignment of timex"][::std::mem::align_of::() - 4usize]; + ["Offset of field: timex::tai"][::std::mem::offset_of!(timex, tai) - 0usize]; +}; +impl Default for timex { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct timex_named { + pub tai: ::std::os::raw::c_int, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 44usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of timex_named"][::std::mem::size_of::() - 48usize]; + ["Alignment of timex_named"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: timex_named::tai", + ][::std::mem::offset_of!(timex_named, tai) - 0usize]; +}; +impl Default for timex_named { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl timex_named { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 32u8) as u32) } + } + #[inline] + pub fn set_a(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn a_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_a_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn b(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 32u8) as u32) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(32usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 32usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 32usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn c(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(64usize, 32u8) as u32) } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(64usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn c_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 64usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_c_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 64usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn d(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(96usize, 32u8) as u32) } + } + #[inline] + pub fn set_d(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(96usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn d_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 96usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_d_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 96usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn e(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(128usize, 32u8) as u32) } + } + #[inline] + pub fn set_e(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(128usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn e_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 128usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_e_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 128usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn f(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(160usize, 32u8) as u32) } + } + #[inline] + pub fn set_f(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(160usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn f_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 160usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_f_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 160usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn g(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(192usize, 32u8) as u32) } + } + #[inline] + pub fn set_g(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(192usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn g_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 192usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_g_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 192usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn h(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(224usize, 32u8) as u32) } + } + #[inline] + pub fn set_h(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(224usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn h_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 224usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_h_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 224usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn i(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(256usize, 32u8) as u32) } + } + #[inline] + pub fn set_i(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(256usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn i_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 256usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_i_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 256usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn j(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(288usize, 32u8) as u32) } + } + #[inline] + pub fn set_j(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(288usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn j_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 288usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_j_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 288usize, + 32u8, + val as u64, + ) + } + } + #[inline] + pub fn k(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(320usize, 32u8) as u32) } + } + #[inline] + pub fn set_k(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(320usize, 32u8, val as u64) + } + } + #[inline] + pub unsafe fn k_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 320usize, 32u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_k_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 44usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 320usize, + 32u8, + val as u64, + ) + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/transform-op.rs b/bindgen-tests/tests/expectations/tests/transform-op.rs new file mode 100644 index 0000000000..7a12f2abb7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/transform-op.rs @@ -0,0 +1,251 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StylePoint { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub x: T, + pub y: T, +} +impl Default for StylePoint { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(1))] +pub struct StyleFoo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub __bindgen_anon_1: __BindgenUnionField, + pub foo: __BindgenUnionField>, + pub bar: __BindgenUnionField>, + pub baz: __BindgenUnionField>, + pub bindgen_union_field: [u8; 0usize], +} +pub const StyleFoo_Tag_Foo: StyleFoo_Tag = 0; +pub const StyleFoo_Tag_Bar: StyleFoo_Tag = 0; +pub const StyleFoo_Tag_Baz: StyleFoo_Tag = 0; +pub const StyleFoo_Tag_Bazz: StyleFoo_Tag = 0; +pub type StyleFoo_Tag = u8; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleFoo_Foo_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub tag: StyleFoo_Tag, + pub x: i32, + pub y: StylePoint, + pub z: StylePoint, +} +impl Default for StyleFoo_Foo_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleFoo_Bar_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub tag: StyleFoo_Tag, + pub _0: T, +} +impl Default for StyleFoo_Bar_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleFoo_Baz_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub tag: StyleFoo_Tag, + pub _0: StylePoint, +} +impl Default for StyleFoo_Baz_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleFoo__bindgen_ty_1 { + pub tag: StyleFoo_Tag, +} +impl Default for StyleFoo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for StyleFoo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct StyleBar { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub tag: StyleBar_Tag, + pub __bindgen_anon_1: StyleBar__bindgen_ty_1, +} +pub const StyleBar_Tag_Bar1: StyleBar_Tag = 0; +pub const StyleBar_Tag_Bar2: StyleBar_Tag = 0; +pub const StyleBar_Tag_Bar3: StyleBar_Tag = 0; +pub const StyleBar_Tag_Bar4: StyleBar_Tag = 0; +pub type StyleBar_Tag = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleBar_StyleBar1_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub x: i32, + pub y: StylePoint, + pub z: StylePoint, +} +impl Default for StyleBar_StyleBar1_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleBar_StyleBar2_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _0: T, +} +impl Default for StyleBar_StyleBar2_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleBar_StyleBar3_Body { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub _0: StylePoint, +} +impl Default for StyleBar_StyleBar3_Body { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(1))] +pub struct StyleBar__bindgen_ty_1 { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub bar1: __BindgenUnionField>, + pub bar2: __BindgenUnionField>, + pub bar3: __BindgenUnionField>, + pub bindgen_union_field: [u8; 0usize], +} +impl Default for StyleBar__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for StyleBar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: StylePoint_open0_float_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: StylePoint_open0_float_close0", + ][::std::mem::align_of::>() - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: StylePoint_open0_float_close0", + ][::std::mem::size_of::>() - 8usize]; + [ + "Align of template specialization: StylePoint_open0_float_close0", + ][::std::mem::align_of::>() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/type-referenced-by-allowlisted-function.rs b/bindgen-tests/tests/expectations/tests/type-referenced-by-allowlisted-function.rs new file mode 100644 index 0000000000..6d1c43d9cc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/type-referenced-by-allowlisted-function.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct dl_phdr_info { + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of dl_phdr_info"][::std::mem::size_of::() - 4usize]; + ["Alignment of dl_phdr_info"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: dl_phdr_info::x", + ][::std::mem::offset_of!(dl_phdr_info, x) - 0usize]; +}; +unsafe extern "C" { + pub fn dl_iterate_phdr(arg1: *mut dl_phdr_info) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/type_alias_empty.rs b/bindgen-tests/tests/expectations/tests/type_alias_empty.rs new file mode 100644 index 0000000000..2cbeb75570 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/type_alias_empty.rs @@ -0,0 +1,2 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type bool_constant = u8; diff --git a/bindgen-tests/tests/expectations/tests/type_alias_partial_template_especialization.rs b/bindgen-tests/tests/expectations/tests/type_alias_partial_template_especialization.rs new file mode 100644 index 0000000000..29df017a9b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/type_alias_partial_template_especialization.rs @@ -0,0 +1,17 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type MaybeWrapped
= A; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub ptr: MaybeWrapped, +} +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/type_alias_template_specialized.rs b/bindgen-tests/tests/expectations/tests/type_alias_template_specialized.rs new file mode 100644 index 0000000000..13e3f8139c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/type_alias_template_specialized.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub ptr: MaybeWrapped<::std::os::raw::c_int>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Rooted"][::std::mem::size_of::() - 4usize]; + ["Alignment of Rooted"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Rooted::ptr"][::std::mem::offset_of!(Rooted, ptr) - 0usize]; +}; +impl Default for Rooted { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +///
+pub type MaybeWrapped
= a; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: MaybeWrapped_open0_int_close0", + ][::std::mem::size_of::>() - 4usize]; + [ + "Align of template specialization: MaybeWrapped_open0_int_close0", + ][::std::mem::align_of::>() - 4usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/typedef-pointer-overlap.rs b/bindgen-tests/tests/expectations/tests/typedef-pointer-overlap.rs new file mode 100644 index 0000000000..122059b4e1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/typedef-pointer-overlap.rs @@ -0,0 +1,87 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub inner: ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of foo"][::std::mem::align_of::() - 1usize]; + ["Offset of field: foo::inner"][::std::mem::offset_of!(foo, inner) - 0usize]; +}; +pub type foo_ptr = *const foo; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar { + pub inner: ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of bar"][::std::mem::align_of::() - 1usize]; + ["Offset of field: bar::inner"][::std::mem::offset_of!(bar, inner) - 0usize]; +}; +pub type bar_ptr = *mut bar; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct baz { + _unused: [u8; 0], +} +pub type baz_ptr = *mut baz; +#[repr(C)] +#[derive(Copy, Clone)] +pub union cat { + pub standard_issue: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cat"][::std::mem::size_of::() - 4usize]; + ["Alignment of cat"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: cat::standard_issue", + ][::std::mem::offset_of!(cat, standard_issue) - 0usize]; +}; +impl Default for cat { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type cat_ptr = *mut cat; +pub const mad_scientist: mad = 0; +pub type mad = ::std::os::raw::c_uint; +pub type mad_ptr = *mut mad; +unsafe extern "C" { + pub fn takes_foo_ptr(arg1: foo_ptr); +} +unsafe extern "C" { + pub fn takes_foo_struct(arg1: foo); +} +unsafe extern "C" { + pub fn takes_bar_ptr(arg1: bar_ptr); +} +unsafe extern "C" { + pub fn takes_bar_struct(arg1: bar); +} +unsafe extern "C" { + pub fn takes_baz_ptr(arg1: baz_ptr); +} +unsafe extern "C" { + pub fn takes_baz_struct(arg1: baz); +} +unsafe extern "C" { + pub fn takes_cat_ptr(arg1: cat_ptr); +} +unsafe extern "C" { + pub fn takes_cat_union(arg1: cat); +} +unsafe extern "C" { + pub fn takes_mad_ptr(arg1: mad_ptr); +} +unsafe extern "C" { + pub fn takes_mad_enum(arg1: mad); +} diff --git a/bindgen-tests/tests/expectations/tests/typedefd-array-as-function-arg.rs b/bindgen-tests/tests/expectations/tests/typedefd-array-as-function-arg.rs new file mode 100644 index 0000000000..994b327da7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/typedefd-array-as-function-arg.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type myVector3 = [f32; 3usize]; +unsafe extern "C" { + pub fn modifyVectorFunc(v: *mut f32); +} diff --git a/bindgen-tests/tests/expectations/tests/typeref.rs b/bindgen-tests/tests/expectations/tests/typeref.rs new file mode 100644 index 0000000000..e48f0eb254 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/typeref.rs @@ -0,0 +1,105 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct mozilla_FragmentOrURL { + pub mIsLocalRef: bool, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of mozilla_FragmentOrURL", + ][::std::mem::size_of::() - 1usize]; + [ + "Alignment of mozilla_FragmentOrURL", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: mozilla_FragmentOrURL::mIsLocalRef", + ][::std::mem::offset_of!(mozilla_FragmentOrURL, mIsLocalRef) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct mozilla_Position { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mozilla_Position"][::std::mem::size_of::() - 1usize]; + [ + "Alignment of mozilla_Position", + ][::std::mem::align_of::() - 1usize]; +}; +#[repr(C)] +pub struct mozilla_StyleShapeSource { + pub __bindgen_anon_1: mozilla_StyleShapeSource__bindgen_ty_1, +} +#[repr(C)] +pub union mozilla_StyleShapeSource__bindgen_ty_1 { + pub mPosition: *mut mozilla_Position, + pub mFragmentOrURL: *mut mozilla_FragmentOrURL, +} +impl Default for mozilla_StyleShapeSource__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for mozilla_StyleShapeSource { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Bar { + pub mFoo: *mut nsFoo, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 8usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 8usize]; + ["Offset of field: Bar::mFoo"][::std::mem::offset_of!(Bar, mFoo) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct nsFoo { + pub mBar: mozilla_StyleShapeSource, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsFoo"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsFoo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: nsFoo::mBar"][::std::mem::offset_of!(nsFoo, mBar) - 0usize]; +}; +impl Default for nsFoo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of template specialization: mozilla_StyleShapeSource_open0_int_close0", + ][::std::mem::size_of::() - 8usize]; + [ + "Align of template specialization: mozilla_StyleShapeSource_open0_int_close0", + ][::std::mem::align_of::() - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/uncallable_functions.rs b/bindgen-tests/tests/expectations/tests/uncallable_functions.rs new file mode 100644 index 0000000000..fddb5d41fc --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/uncallable_functions.rs @@ -0,0 +1,46 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct Test__bindgen_vtable { + pub Test_a: unsafe extern "C" fn(this: *mut Test), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Test { + pub vtable_: *const Test__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Test"][::std::mem::size_of::() - 8usize]; + ["Alignment of Test"][::std::mem::align_of::() - 8usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Test1bEv"] + pub fn Test_b(this: *mut Test); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Test1cEv"] + pub fn Test_c(this: *mut Test); +} +impl Default for Test { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Test { + #[inline] + pub unsafe fn b(&mut self) { + Test_b(self) + } + #[inline] + pub unsafe fn c(&mut self) { + Test_c(self) + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Test1aEv"] + pub fn Test_a(this: *mut ::std::os::raw::c_void); +} diff --git a/bindgen-tests/tests/expectations/tests/underscore.rs b/bindgen-tests/tests/expectations/tests/underscore.rs new file mode 100644 index 0000000000..f94d5fc580 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/underscore.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub const __: ::std::os::raw::c_int = 10; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ptr_t { + pub __: [::std::os::raw::c_uchar; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ptr_t"][::std::mem::size_of::() - 8usize]; + ["Alignment of ptr_t"][::std::mem::align_of::() - 1usize]; + ["Offset of field: ptr_t::__"][::std::mem::offset_of!(ptr_t, __) - 0usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/union-align.rs b/bindgen-tests/tests/expectations/tests/union-align.rs new file mode 100644 index 0000000000..bdb1bb376e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union-align.rs @@ -0,0 +1,43 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(16))] +#[derive(Copy, Clone)] +pub union Bar { + pub foo: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 16usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Bar::foo"][::std::mem::offset_of!(Bar, foo) - 0usize]; +}; +impl Default for Bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Copy, Clone)] +pub union Baz { + pub bar: Bar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 16usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Baz::bar"][::std::mem::offset_of!(Baz, bar) - 0usize]; +}; +impl Default for Baz { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union-in-ns.rs b/bindgen-tests/tests/expectations/tests/union-in-ns.rs new file mode 100644 index 0000000000..781041addb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union-in-ns.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Copy, Clone)] + pub union bar { + pub baz: ::std::os::raw::c_int, + } + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + ["Size of bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: bar::baz"][::std::mem::offset_of!(bar, baz) - 0usize]; + }; + impl Default for bar { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_bitfield.rs new file mode 100644 index 0000000000..8df0724738 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_bitfield.rs @@ -0,0 +1,340 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union U4 { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of U4"][::std::mem::size_of::() - 4usize]; + ["Alignment of U4"][::std::mem::align_of::() - 4usize]; +}; +impl Default for U4 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl U4 { + #[inline] + pub fn derp(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn derp_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_derp_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + derp: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let derp: u32 = unsafe { ::std::mem::transmute(derp) }; + derp as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union B { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of B"][::std::mem::size_of::() - 4usize]; + ["Alignment of B"][::std::mem::align_of::() - 4usize]; +}; +impl Default for B { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl B { + #[inline] + pub fn foo(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 31u8) as u32) } + } + #[inline] + pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 31u8, val as u64) + } + } + #[inline] + pub unsafe fn foo_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 31u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_foo_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 31u8, + val as u64, + ) + } + } + #[inline] + pub fn bar(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } + } + #[inline] + pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn bar_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_bar_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + foo: ::std::os::raw::c_uint, + bar: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 31u8, + { + let foo: u32 = unsafe { ::std::mem::transmute(foo) }; + foo as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 0usize, + 1u8, + { + let bar: u8 = unsafe { ::std::mem::transmute(bar) }; + bar as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_dtor.rs b/bindgen-tests/tests/expectations/tests/union_dtor.rs new file mode 100644 index 0000000000..3b89587098 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_dtor.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub union UnionWithDtor { + pub mFoo: ::std::os::raw::c_int, + pub mBar: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of UnionWithDtor"][::std::mem::size_of::() - 8usize]; + ["Alignment of UnionWithDtor"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: UnionWithDtor::mFoo", + ][::std::mem::offset_of!(UnionWithDtor, mFoo) - 0usize]; + [ + "Offset of field: UnionWithDtor::mBar", + ][::std::mem::offset_of!(UnionWithDtor, mBar) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN13UnionWithDtorD1Ev"] + pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor); +} +impl Default for UnionWithDtor { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl UnionWithDtor { + #[inline] + pub unsafe fn destruct(&mut self) { + UnionWithDtor_UnionWithDtor_destructor(self) + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_fields.rs b/bindgen-tests/tests/expectations/tests/union_fields.rs new file mode 100644 index 0000000000..c3d0f8db61 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_fields.rs @@ -0,0 +1,31 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union nsStyleUnion { + pub mInt: ::std::os::raw::c_int, + pub mFloat: f32, + pub mPointer: *mut ::std::os::raw::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsStyleUnion"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsStyleUnion"][::std::mem::align_of::() - 8usize]; + [ + "Offset of field: nsStyleUnion::mInt", + ][::std::mem::offset_of!(nsStyleUnion, mInt) - 0usize]; + [ + "Offset of field: nsStyleUnion::mFloat", + ][::std::mem::offset_of!(nsStyleUnion, mFloat) - 0usize]; + [ + "Offset of field: nsStyleUnion::mPointer", + ][::std::mem::offset_of!(nsStyleUnion, mPointer) - 0usize]; +}; +impl Default for nsStyleUnion { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_template.rs b/bindgen-tests/tests/expectations/tests/union_template.rs new file mode 100644 index 0000000000..62019e6dd7 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_template.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct NastyStruct { + pub mIsSome: bool, + pub mStorage: NastyStruct__bindgen_ty_1, + pub __bindgen_anon_1: NastyStruct__bindgen_ty_2, +} +#[repr(C)] +pub union NastyStruct__bindgen_ty_1 { + pub mFoo: *mut ::std::os::raw::c_void, + pub mDummy: ::std::os::raw::c_ulong, +} +impl Default for NastyStruct__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub union NastyStruct__bindgen_ty_2 { + pub wat: ::std::os::raw::c_short, + pub wut: *mut ::std::os::raw::c_int, +} +impl Default for NastyStruct__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for NastyStruct { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub union Whatever { + pub mTPtr: *mut ::std::os::raw::c_void, + pub mInt: ::std::os::raw::c_int, +} +impl Default for Whatever { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_struct.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_struct.rs new file mode 100644 index 0000000000..20f4dd2265 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_struct.rs @@ -0,0 +1,40 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 4usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs new file mode 100644 index 0000000000..a1b61c035d --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs @@ -0,0 +1,281 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo { + pub a: ::std::os::raw::c_int, + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo__bindgen_ty_1 { + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; +}; +impl foo__bindgen_ty_1 { + #[inline] + pub fn b(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u32) } + } + #[inline] + pub fn set_b(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 7u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 7u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 7u8, + val as u64, + ) + } + } + #[inline] + pub fn c(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 25u8) as u32) } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(7usize, 25u8, val as u64) + } + } + #[inline] + pub unsafe fn c_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 7usize, 25u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_c_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 7usize, + 25u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + b: ::std::os::raw::c_int, + c: ::std::os::raw::c_int, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 7u8, + { + let b: u32 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 25u8, + { + let c: u32 = unsafe { ::std::mem::transmute(c) }; + c as u64 + }, + ); + __bindgen_bitfield_unit + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::a"][::std::mem::offset_of!(foo, a) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_union.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_union.rs new file mode 100644 index 0000000000..212a159cd2 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_union.rs @@ -0,0 +1,49 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: foo__bindgen_ty_1::a", + ][::std::mem::offset_of!(foo__bindgen_ty_1, a) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::bar"][::std::mem::offset_of!(foo, bar) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_struct.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_struct.rs new file mode 100644 index 0000000000..859188e891 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_struct.rs @@ -0,0 +1,51 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union pixel { + pub rgba: ::std::os::raw::c_uint, + pub __bindgen_anon_1: pixel__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct pixel__bindgen_ty_1 { + pub r: ::std::os::raw::c_uchar, + pub g: ::std::os::raw::c_uchar, + pub b: ::std::os::raw::c_uchar, + pub a: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of pixel__bindgen_ty_1", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of pixel__bindgen_ty_1", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: pixel__bindgen_ty_1::r", + ][::std::mem::offset_of!(pixel__bindgen_ty_1, r) - 0usize]; + [ + "Offset of field: pixel__bindgen_ty_1::g", + ][::std::mem::offset_of!(pixel__bindgen_ty_1, g) - 1usize]; + [ + "Offset of field: pixel__bindgen_ty_1::b", + ][::std::mem::offset_of!(pixel__bindgen_ty_1, b) - 2usize]; + [ + "Offset of field: pixel__bindgen_ty_1::a", + ][::std::mem::offset_of!(pixel__bindgen_ty_1, a) - 3usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of pixel"][::std::mem::size_of::() - 4usize]; + ["Alignment of pixel"][::std::mem::align_of::() - 4usize]; + ["Offset of field: pixel::rgba"][::std::mem::offset_of!(pixel, rgba) - 0usize]; +}; +impl Default for pixel { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_union.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_union.rs new file mode 100644 index 0000000000..6e136c0d92 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_unnamed_union.rs @@ -0,0 +1,50 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo { + pub a: ::std::os::raw::c_uint, + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1 { + pub b: ::std::os::raw::c_ushort, + pub c: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 2usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: foo__bindgen_ty_1::b", + ][::std::mem::offset_of!(foo__bindgen_ty_1, b) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1::c", + ][::std::mem::offset_of!(foo__bindgen_ty_1, c) - 0usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::a"][::std::mem::offset_of!(foo, a) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_big_member.rs b/bindgen-tests/tests/expectations/tests/union_with_big_member.rs new file mode 100644 index 0000000000..9d69957a85 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_big_member.rs @@ -0,0 +1,79 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union WithBigArray { + pub a: ::std::os::raw::c_int, + pub b: [::std::os::raw::c_int; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithBigArray"][::std::mem::size_of::() - 132usize]; + ["Alignment of WithBigArray"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithBigArray::a", + ][::std::mem::offset_of!(WithBigArray, a) - 0usize]; + [ + "Offset of field: WithBigArray::b", + ][::std::mem::offset_of!(WithBigArray, b) - 0usize]; +}; +impl Default for WithBigArray { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union WithBigArray2 { + pub a: ::std::os::raw::c_int, + pub b: [::std::os::raw::c_char; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithBigArray2"][::std::mem::size_of::() - 36usize]; + ["Alignment of WithBigArray2"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithBigArray2::a", + ][::std::mem::offset_of!(WithBigArray2, a) - 0usize]; + [ + "Offset of field: WithBigArray2::b", + ][::std::mem::offset_of!(WithBigArray2, b) - 0usize]; +}; +impl Default for WithBigArray2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union WithBigMember { + pub a: ::std::os::raw::c_int, + pub b: WithBigArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithBigMember"][::std::mem::size_of::() - 132usize]; + ["Alignment of WithBigMember"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithBigMember::a", + ][::std::mem::offset_of!(WithBigMember, a) - 0usize]; + [ + "Offset of field: WithBigMember::b", + ][::std::mem::offset_of!(WithBigMember, b) - 0usize]; +}; +impl Default for WithBigMember { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_nesting.rs b/bindgen-tests/tests/expectations/tests/union_with_nesting.rs new file mode 100644 index 0000000000..5b60193ba4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_nesting.rs @@ -0,0 +1,104 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo { + pub a: ::std::os::raw::c_uint, + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct foo__bindgen_ty_1 { + pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, + pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1__bindgen_ty_1 { + pub b1: ::std::os::raw::c_ushort, + pub b2: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of foo__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::size_of::() - 2usize]; + [ + "Alignment of foo__bindgen_ty_1__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_1::b1", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_1, b1) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_1::b2", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_1, b2) - 0usize]; +}; +impl Default for foo__bindgen_ty_1__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union foo__bindgen_ty_1__bindgen_ty_2 { + pub c1: ::std::os::raw::c_ushort, + pub c2: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of foo__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::size_of::() - 2usize]; + [ + "Alignment of foo__bindgen_ty_1__bindgen_ty_2", + ][::std::mem::align_of::() - 2usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::c1", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, c1) - 0usize]; + [ + "Offset of field: foo__bindgen_ty_1__bindgen_ty_2::c2", + ][::std::mem::offset_of!(foo__bindgen_ty_1__bindgen_ty_2, c2) - 0usize]; +}; +impl Default for foo__bindgen_ty_1__bindgen_ty_2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo__bindgen_ty_1"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of foo__bindgen_ty_1", + ][::std::mem::align_of::() - 2usize]; +}; +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 4usize]; + ["Alignment of foo"][::std::mem::align_of::() - 4usize]; + ["Offset of field: foo::a"][::std::mem::offset_of!(foo, a) - 0usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_non_copy_member.rs b/bindgen-tests/tests/expectations/tests/union_with_non_copy_member.rs new file mode 100644 index 0000000000..d13c24d2d8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_non_copy_member.rs @@ -0,0 +1,142 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +#[repr(C)] +#[derive(Debug, Default)] +pub struct NonCopyType { + pub foo: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of NonCopyType"][::std::mem::size_of::() - 4usize]; + ["Alignment of NonCopyType"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: NonCopyType::foo", + ][::std::mem::offset_of!(NonCopyType, foo) - 0usize]; +}; +#[repr(C)] +pub struct WithBindgenGeneratedWrapper { + pub non_copy_type: __BindgenUnionField, + pub bar: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of WithBindgenGeneratedWrapper", + ][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WithBindgenGeneratedWrapper", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithBindgenGeneratedWrapper::non_copy_type", + ][::std::mem::offset_of!(WithBindgenGeneratedWrapper, non_copy_type) - 0usize]; + [ + "Offset of field: WithBindgenGeneratedWrapper::bar", + ][::std::mem::offset_of!(WithBindgenGeneratedWrapper, bar) - 0usize]; +}; +impl Default for WithBindgenGeneratedWrapper { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub union WithManuallyDrop { + pub non_copy_type: ::std::mem::ManuallyDrop, + pub bar: ::std::mem::ManuallyDrop<::std::os::raw::c_int>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithManuallyDrop"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WithManuallyDrop", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithManuallyDrop::non_copy_type", + ][::std::mem::offset_of!(WithManuallyDrop, non_copy_type) - 0usize]; + [ + "Offset of field: WithManuallyDrop::bar", + ][::std::mem::offset_of!(WithManuallyDrop, bar) - 0usize]; +}; +impl Default for WithManuallyDrop { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct WithDefaultWrapper { + pub non_copy_type: __BindgenUnionField, + pub bar: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of WithDefaultWrapper"][::std::mem::size_of::() - 4usize]; + [ + "Alignment of WithDefaultWrapper", + ][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: WithDefaultWrapper::non_copy_type", + ][::std::mem::offset_of!(WithDefaultWrapper, non_copy_type) - 0usize]; + [ + "Offset of field: WithDefaultWrapper::bar", + ][::std::mem::offset_of!(WithDefaultWrapper, bar) - 0usize]; +}; +impl Default for WithDefaultWrapper { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/union_with_zero_sized_array.rs b/bindgen-tests/tests/expectations/tests/union_with_zero_sized_array.rs new file mode 100644 index 0000000000..aa23fcd734 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/union_with_zero_sized_array.rs @@ -0,0 +1,68 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +#[repr(C)] +pub struct U { + pub d0: __BindgenUnionField<[::std::os::raw::c_char; 0usize]>, + pub d1: __BindgenUnionField<[::std::os::raw::c_char; 1usize]>, + pub d2: __BindgenUnionField<[::std::os::raw::c_char; 2usize]>, + pub bindgen_union_field: [u8; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of U"][::std::mem::size_of::() - 2usize]; + ["Alignment of U"][::std::mem::align_of::() - 1usize]; + ["Offset of field: U::d0"][::std::mem::offset_of!(U, d0) - 0usize]; + ["Offset of field: U::d1"][::std::mem::offset_of!(U, d1) - 0usize]; + ["Offset of field: U::d2"][::std::mem::offset_of!(U, d2) - 0usize]; +}; +impl Default for U { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/unknown_attr.rs b/bindgen-tests/tests/expectations/tests/unknown_attr.rs new file mode 100644 index 0000000000..d749dad977 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/unknown_attr.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct max_align_t { + pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, + pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 8usize]>, + pub __clang_max_align_nonce2: ::std::os::raw::c_longlong, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of max_align_t"][::std::mem::size_of::() - 32usize]; + ["Alignment of max_align_t"][::std::mem::align_of::() - 16usize]; + [ + "Offset of field: max_align_t::__clang_max_align_nonce1", + ][::std::mem::offset_of!(max_align_t, __clang_max_align_nonce1) - 0usize]; + [ + "Offset of field: max_align_t::__clang_max_align_nonce2", + ][::std::mem::offset_of!(max_align_t, __clang_max_align_nonce2) - 16usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/unsorted-items.rs b/bindgen-tests/tests/expectations/tests/unsorted-items.rs new file mode 100644 index 0000000000..7d31c222a1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/unsorted-items.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn foo() -> ::std::os::raw::c_int; +} +pub type number = ::std::os::raw::c_int; +unsafe extern "C" { + pub fn bar(x: number) -> ::std::os::raw::c_int; +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Point { + pub x: number, + pub y: number, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Point"][::std::mem::size_of::() - 8usize]; + ["Alignment of Point"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Point::x"][::std::mem::offset_of!(Point, x) - 0usize]; + ["Offset of field: Point::y"][::std::mem::offset_of!(Point, y) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Angle { + pub a: number, + pub b: number, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Angle"][::std::mem::size_of::() - 8usize]; + ["Alignment of Angle"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Angle::a"][::std::mem::offset_of!(Angle, a) - 0usize]; + ["Offset of field: Angle::b"][::std::mem::offset_of!(Angle, b) - 4usize]; +}; +unsafe extern "C" { + pub fn baz(point: Point) -> ::std::os::raw::c_int; +} +pub const NUMBER: number = 42; diff --git a/bindgen-tests/tests/expectations/tests/use-core.rs b/bindgen-tests/tests/expectations/tests/use-core.rs new file mode 100644 index 0000000000..8d495459a0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/use-core.rs @@ -0,0 +1,59 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(target_os = "windows"))] +extern crate core; +#[repr(C)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct foo { + pub a: ::core::ffi::c_int, + pub b: ::core::ffi::c_int, + pub bar: *mut ::core::ffi::c_void, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::core::mem::size_of::() - 16usize]; + ["Alignment of foo"][::core::mem::align_of::() - 8usize]; + ["Offset of field: foo::a"][::core::mem::offset_of!(foo, a) - 0usize]; + ["Offset of field: foo::b"][::core::mem::offset_of!(foo, b) - 4usize]; + ["Offset of field: foo::bar"][::core::mem::offset_of!(foo, bar) - 8usize]; +}; +impl Default for foo { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union _bindgen_ty_1 { + pub bar: ::core::ffi::c_int, + pub baz: ::core::ffi::c_long, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of _bindgen_ty_1"][::core::mem::size_of::<_bindgen_ty_1>() - 8usize]; + ["Alignment of _bindgen_ty_1"][::core::mem::align_of::<_bindgen_ty_1>() - 8usize]; + [ + "Offset of field: _bindgen_ty_1::bar", + ][::core::mem::offset_of!(_bindgen_ty_1, bar) - 0usize]; + [ + "Offset of field: _bindgen_ty_1::baz", + ][::core::mem::offset_of!(_bindgen_ty_1, baz) - 0usize]; +}; +impl Default for _bindgen_ty_1 { + fn default() -> Self { + let mut s = ::core::mem::MaybeUninit::::uninit(); + unsafe { + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + pub static mut bazz: _bindgen_ty_1; +} +pub type fooFunction = ::core::option::Option< + unsafe extern "C" fn(bar: ::core::ffi::c_int), +>; diff --git a/bindgen-tests/tests/expectations/tests/using.rs b/bindgen-tests/tests/expectations/tests/using.rs new file mode 100644 index 0000000000..9737fef0a5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/using.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Point { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub x: T, + pub y: T, +} +impl Default for Point { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type IntPoint2D = Point<::std::os::raw::c_int>; +pub type IntVec2D = Point<::std::os::raw::c_int>; diff --git a/bindgen-tests/tests/expectations/tests/va_list_aarch64_linux.rs b/bindgen-tests/tests/expectations/tests/va_list_aarch64_linux.rs new file mode 100644 index 0000000000..b33f4894c1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/va_list_aarch64_linux.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] +#[repr(C, align(8))] +pub struct __BindgenOpaqueArray8(pub T); +impl Default for __BindgenOpaqueArray8<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } +} +pub type va_list = __BindgenOpaqueArray8<[u8; 32usize]>; +unsafe extern "C" { + pub fn vprintf( + format: *const ::std::os::raw::c_char, + vlist: __BindgenOpaqueArray8<[u8; 32usize]>, + ) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/var-tracing.rs b/bindgen-tests/tests/expectations/tests/var-tracing.rs new file mode 100644 index 0000000000..76ce0c50d6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/var-tracing.rs @@ -0,0 +1,38 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub m_baz: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 4usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 4usize]; + ["Offset of field: Bar::m_baz"][::std::mem::offset_of!(Bar, m_baz) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3BarC1Ei"] + pub fn Bar_Bar(this: *mut Bar, baz: ::std::os::raw::c_int); +} +impl Bar { + #[inline] + pub unsafe fn new(baz: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + Bar_Bar(__bindgen_tmp.as_mut_ptr(), baz); + __bindgen_tmp.assume_init() + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Baz { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Baz3FOOE"] + pub static Baz_FOO: [Bar; 0usize]; +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Baz"][::std::mem::size_of::() - 1usize]; + ["Alignment of Baz"][::std::mem::align_of::() - 1usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/variadic-method.rs b/bindgen-tests/tests/expectations/tests/variadic-method.rs new file mode 100644 index 0000000000..deac5f719e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/variadic-method.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooPKcz"] + pub fn foo(fmt: *const ::std::os::raw::c_char, ...); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Bar"][::std::mem::size_of::() - 1usize]; + ["Alignment of Bar"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3Bar3fooEPKcz"] + pub fn Bar_foo(this: *mut Bar, fmt: *const ::std::os::raw::c_char, ...); +} diff --git a/bindgen-tests/tests/expectations/tests/variadic-union.rs b/bindgen-tests/tests/expectations/tests/variadic-union.rs new file mode 100644 index 0000000000..471c9e7075 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/variadic-union.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub union _Variadic_union { + pub _address: u8, +} +impl Default for _Variadic_union { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/variadic_template_function.rs b/bindgen-tests/tests/expectations/tests/variadic_template_function.rs similarity index 79% rename from tests/expectations/tests/variadic_template_function.rs rename to bindgen-tests/tests/expectations/tests/variadic_template_function.rs index e14da64f33..ee945f2599 100644 --- a/tests/expectations/tests/variadic_template_function.rs +++ b/bindgen-tests/tests/expectations/tests/variadic_template_function.rs @@ -1,9 +1,4 @@ -/* automatically generated by rust-bindgen */ - - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct VariadicFunctionObject { diff --git a/bindgen-tests/tests/expectations/tests/vector.rs b/bindgen-tests/tests/expectations/tests/vector.rs new file mode 100644 index 0000000000..da53b4a8eb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/vector.rs @@ -0,0 +1,19 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub mMember: [::std::os::raw::c_longlong; 1usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of foo"][::std::mem::size_of::() - 8usize]; + ["Alignment of foo"][::std::mem::align_of::() - 8usize]; + ["Offset of field: foo::mMember"][::std::mem::offset_of!(foo, mMember) - 0usize]; +}; +pub type __m128 = [f32; 4usize]; +pub type __m128d = [f64; 2usize]; +pub type __m128i = [::std::os::raw::c_longlong; 2usize]; +unsafe extern "C" { + #[link_name = "\u{1}_Z3fooDv2_xDv2_d"] + pub fn foo(arg1: __m128i, arg2: __m128d) -> __m128; +} diff --git a/bindgen-tests/tests/expectations/tests/virtual_dtor.rs b/bindgen-tests/tests/expectations/tests/virtual_dtor.rs new file mode 100644 index 0000000000..d42be25202 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/virtual_dtor.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct nsSlots__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug)] +pub struct nsSlots { + pub vtable_: *const nsSlots__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of nsSlots"][::std::mem::size_of::() - 8usize]; + ["Alignment of nsSlots"][::std::mem::align_of::() - 8usize]; +}; +impl Default for nsSlots { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN7nsSlotsD1Ev"] + pub fn nsSlots_nsSlots_destructor(this: *mut nsSlots); +} diff --git a/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs b/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs new file mode 100644 index 0000000000..6b5a855fae --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs @@ -0,0 +1,56 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub foo: ::std::os::raw::c_int, +} +#[repr(C)] +pub struct B__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct B { + pub vtable_: *const B__bindgen_vtable, + pub bar: ::std::os::raw::c_int, +} +impl Default for B { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct C__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub vtable_: *const C__bindgen_vtable, + pub baz: ::std::os::raw::c_int, +} +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct D { + pub _base: C, + pub _base_1: B, + pub bazz: ::std::os::raw::c_int, +} +impl Default for D { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/virtual_interface.rs b/bindgen-tests/tests/expectations/tests/virtual_interface.rs new file mode 100644 index 0000000000..44b245c4ea --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/virtual_interface.rs @@ -0,0 +1,94 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct PureVirtualIFace__bindgen_vtable { + pub PureVirtualIFace_Foo: unsafe extern "C" fn(this: *mut PureVirtualIFace), + pub PureVirtualIFace_Bar: unsafe extern "C" fn( + this: *mut PureVirtualIFace, + arg1: ::std::os::raw::c_uint, + ), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PureVirtualIFace { + pub vtable_: *const PureVirtualIFace__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of PureVirtualIFace"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of PureVirtualIFace", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for PureVirtualIFace { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct AnotherInterface__bindgen_vtable { + pub AnotherInterface_Baz: unsafe extern "C" fn(this: *mut AnotherInterface), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AnotherInterface { + pub vtable_: *const AnotherInterface__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AnotherInterface"][::std::mem::size_of::() - 8usize]; + [ + "Alignment of AnotherInterface", + ][::std::mem::align_of::() - 8usize]; +}; +impl Default for AnotherInterface { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Implementation { + pub _base: PureVirtualIFace, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Implementation"][::std::mem::size_of::() - 8usize]; + ["Alignment of Implementation"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Implementation { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DoubleImpl { + pub _base: PureVirtualIFace, + pub _base_1: AnotherInterface, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of DoubleImpl"][::std::mem::size_of::() - 16usize]; + ["Alignment of DoubleImpl"][::std::mem::align_of::() - 8usize]; +}; +impl Default for DoubleImpl { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/virtual_overloaded.rs b/bindgen-tests/tests/expectations/tests/virtual_overloaded.rs new file mode 100644 index 0000000000..4c3702faeb --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/virtual_overloaded.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct C__bindgen_vtable { + pub C_do_thing: unsafe extern "C" fn(this: *mut C, arg1: ::std::os::raw::c_char), + pub C_do_thing1: unsafe extern "C" fn(this: *mut C, arg1: ::std::os::raw::c_int), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub vtable_: *const C__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of C"][::std::mem::size_of::() - 8usize]; + ["Alignment of C"][::std::mem::align_of::() - 8usize]; +}; +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C8do_thingEc"] + pub fn C_do_thing(this: *mut ::std::os::raw::c_void, arg1: ::std::os::raw::c_char); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN1C8do_thingEi"] + pub fn C_do_thing1(this: *mut ::std::os::raw::c_void, arg1: ::std::os::raw::c_int); +} diff --git a/bindgen-tests/tests/expectations/tests/void_typedef.rs b/bindgen-tests/tests/expectations/tests/void_typedef.rs new file mode 100644 index 0000000000..4997d49086 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/void_typedef.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub type VOID = ::std::os::raw::c_void; +pub type ALSO_VOID = VOID; +unsafe extern "C" { + pub fn this_api_returns_nothing(); +} +unsafe extern "C" { + pub fn this_api_also_returns_nothing(); +} +unsafe extern "C" { + pub fn this_other_api_also_returns_nothing(); +} diff --git a/bindgen-tests/tests/expectations/tests/vtable_recursive_sig.rs b/bindgen-tests/tests/expectations/tests/vtable_recursive_sig.rs new file mode 100644 index 0000000000..9b9c2467aa --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/vtable_recursive_sig.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct Base__bindgen_vtable { + pub Base_AsDerived: unsafe extern "C" fn(this: *mut Base) -> *mut Derived, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Base { + pub vtable_: *const Base__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Base"][::std::mem::size_of::() - 8usize]; + ["Alignment of Base"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Base { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Base9AsDerivedEv"] + pub fn Base_AsDerived(this: *mut ::std::os::raw::c_void) -> *mut Derived; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Derived { + pub _base: Base, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Derived"][::std::mem::size_of::() - 8usize]; + ["Alignment of Derived"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Derived { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/wasm-constructor-returns.rs b/bindgen-tests/tests/expectations/tests/wasm-constructor-returns.rs new file mode 100644 index 0000000000..ee26600a6b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wasm-constructor-returns.rs @@ -0,0 +1,26 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}_ZN3FooC1Ei"] + pub fn Foo_Foo( + this: *mut Foo, + var: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_void; +} +impl Foo { + #[inline] + pub unsafe fn new(var: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + Foo_Foo(__bindgen_tmp.as_mut_ptr(), var); + __bindgen_tmp.assume_init() + } +} diff --git a/bindgen-tests/tests/expectations/tests/wasm-import-module.rs b/bindgen-tests/tests/expectations/tests/wasm-import-module.rs new file mode 100644 index 0000000000..aeeb17f1c1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wasm-import-module.rs @@ -0,0 +1,5 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[link(wasm_import_module = "test-module")] +unsafe extern "C" { + pub fn test_function(); +} diff --git a/bindgen-tests/tests/expectations/tests/weird_bitfields.rs b/bindgen-tests/tests/expectations/tests/weird_bitfields.rs new file mode 100644 index 0000000000..ca8d84520b --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/weird_bitfields.rs @@ -0,0 +1,574 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum nsStyleSVGOpacitySource { + eStyleSVGOpacitySource_Normal = 0, + eStyleSVGOpacitySource_ContextFillOpacity = 1, + eStyleSVGOpacitySource_ContextStrokeOpacity = 2, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Weird { + pub mStrokeDasharrayLength: ::std::os::raw::c_uint, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, + pub mClipRule: ::std::os::raw::c_uchar, + pub mColorInterpolation: ::std::os::raw::c_uchar, + pub mColorInterpolationFilters: ::std::os::raw::c_uchar, + pub mFillRule: ::std::os::raw::c_uchar, + pub mImageRendering: ::std::os::raw::c_uchar, + pub mPaintOrder: ::std::os::raw::c_uchar, + pub mShapeRendering: ::std::os::raw::c_uchar, + pub mStrokeLinecap: ::std::os::raw::c_uchar, + pub mStrokeLinejoin: ::std::os::raw::c_uchar, + pub mTextAnchor: ::std::os::raw::c_uchar, + pub mTextRendering: ::std::os::raw::c_uchar, + pub _bitfield_2: __BindgenBitfieldUnit<[u8; 2usize]>, + pub __bindgen_padding_0: [u8; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Weird"][::std::mem::size_of::() - 24usize]; + ["Alignment of Weird"][::std::mem::align_of::() - 4usize]; + [ + "Offset of field: Weird::mStrokeDasharrayLength", + ][::std::mem::offset_of!(Weird, mStrokeDasharrayLength) - 0usize]; + [ + "Offset of field: Weird::mClipRule", + ][::std::mem::offset_of!(Weird, mClipRule) - 8usize]; + [ + "Offset of field: Weird::mColorInterpolation", + ][::std::mem::offset_of!(Weird, mColorInterpolation) - 9usize]; + [ + "Offset of field: Weird::mColorInterpolationFilters", + ][::std::mem::offset_of!(Weird, mColorInterpolationFilters) - 10usize]; + [ + "Offset of field: Weird::mFillRule", + ][::std::mem::offset_of!(Weird, mFillRule) - 11usize]; + [ + "Offset of field: Weird::mImageRendering", + ][::std::mem::offset_of!(Weird, mImageRendering) - 12usize]; + [ + "Offset of field: Weird::mPaintOrder", + ][::std::mem::offset_of!(Weird, mPaintOrder) - 13usize]; + [ + "Offset of field: Weird::mShapeRendering", + ][::std::mem::offset_of!(Weird, mShapeRendering) - 14usize]; + [ + "Offset of field: Weird::mStrokeLinecap", + ][::std::mem::offset_of!(Weird, mStrokeLinecap) - 15usize]; + [ + "Offset of field: Weird::mStrokeLinejoin", + ][::std::mem::offset_of!(Weird, mStrokeLinejoin) - 16usize]; + [ + "Offset of field: Weird::mTextAnchor", + ][::std::mem::offset_of!(Weird, mTextAnchor) - 17usize]; + [ + "Offset of field: Weird::mTextRendering", + ][::std::mem::offset_of!(Weird, mTextRendering) - 18usize]; +}; +impl Default for Weird { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Weird { + #[inline] + pub fn bitTest(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) } + } + #[inline] + pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn bitTest_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 16u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bitTest_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn bitTest2(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 15u8) as u32) } + } + #[inline] + pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 15u8, val as u64) + } + } + #[inline] + pub unsafe fn bitTest2_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 16usize, 15u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_bitTest2_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 4usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 16usize, + 15u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + bitTest: ::std::os::raw::c_uint, + bitTest2: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 16u8, + { + let bitTest: u32 = unsafe { ::std::mem::transmute(bitTest) }; + bitTest as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 16usize, + 15u8, + { + let bitTest2: u32 = unsafe { ::std::mem::transmute(bitTest2) }; + bitTest2 as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource { + unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 3u8) as u32) } + } + #[inline] + pub fn set_mFillOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_2.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn mFillOpacitySource_raw(this: *const Self) -> nsStyleSVGOpacitySource { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 0usize, 3u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_mFillOpacitySource_raw( + this: *mut Self, + val: nsStyleSVGOpacitySource, + ) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 0usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn mStrokeOpacitySource(&self) -> nsStyleSVGOpacitySource { + unsafe { ::std::mem::transmute(self._bitfield_2.get(3usize, 3u8) as u32) } + } + #[inline] + pub fn set_mStrokeOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_2.set(3usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn mStrokeOpacitySource_raw( + this: *const Self, + ) -> nsStyleSVGOpacitySource { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 3usize, 3u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_mStrokeOpacitySource_raw( + this: *mut Self, + val: nsStyleSVGOpacitySource, + ) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 3usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn mStrokeDasharrayFromObject(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_2.get(6usize, 1u8) as u8) } + } + #[inline] + pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(6usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn mStrokeDasharrayFromObject_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 6usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_mStrokeDasharrayFromObject_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 6usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn mStrokeDashoffsetFromObject(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_2.get(7usize, 1u8) as u8) } + } + #[inline] + pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(7usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn mStrokeDashoffsetFromObject_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 7usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_mStrokeDashoffsetFromObject_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 7usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn mStrokeWidthFromObject(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_2.get(8usize, 1u8) as u8) } + } + #[inline] + pub fn set_mStrokeWidthFromObject(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(8usize, 1u8, val as u64) + } + } + #[inline] + pub unsafe fn mStrokeWidthFromObject_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 8usize, 1u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_mStrokeWidthFromObject_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 8usize, + 1u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_2( + mFillOpacitySource: nsStyleSVGOpacitySource, + mStrokeOpacitySource: nsStyleSVGOpacitySource, + mStrokeDasharrayFromObject: bool, + mStrokeDashoffsetFromObject: bool, + mStrokeWidthFromObject: bool, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 3u8, + { + let mFillOpacitySource: u32 = unsafe { + ::std::mem::transmute(mFillOpacitySource) + }; + mFillOpacitySource as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 3usize, + 3u8, + { + let mStrokeOpacitySource: u32 = unsafe { + ::std::mem::transmute(mStrokeOpacitySource) + }; + mStrokeOpacitySource as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 6usize, + 1u8, + { + let mStrokeDasharrayFromObject: u8 = unsafe { + ::std::mem::transmute(mStrokeDasharrayFromObject) + }; + mStrokeDasharrayFromObject as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 7usize, + 1u8, + { + let mStrokeDashoffsetFromObject: u8 = unsafe { + ::std::mem::transmute(mStrokeDashoffsetFromObject) + }; + mStrokeDashoffsetFromObject as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 1u8, + { + let mStrokeWidthFromObject: u8 = unsafe { + ::std::mem::transmute(mStrokeWidthFromObject) + }; + mStrokeWidthFromObject as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/what_is_going_on.rs b/bindgen-tests/tests/expectations/tests/what_is_going_on.rs new file mode 100644 index 0000000000..aaeab668e1 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/what_is_going_on.rs @@ -0,0 +1,29 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct UnknownUnits { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of UnknownUnits"][::std::mem::size_of::() - 1usize]; + ["Alignment of UnknownUnits"][::std::mem::align_of::() - 1usize]; +}; +pub type Float = f32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PointTyped { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub x: F, + pub y: F, +} +impl Default for PointTyped { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub type IntPoint = PointTyped; diff --git a/bindgen-tests/tests/expectations/tests/win32-dtors.rs b/bindgen-tests/tests/expectations/tests/win32-dtors.rs new file mode 100644 index 0000000000..d7ed1290f8 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-dtors.rs @@ -0,0 +1,145 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default)] +pub struct CppObj { + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of CppObj"][::std::mem::size_of::() - 4usize]; + ["Alignment of CppObj"][::std::mem::align_of::() - 4usize]; + ["Offset of field: CppObj::x"][::std::mem::offset_of!(CppObj, x) - 0usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}??0CppObj@@QEAA@H@Z"] + pub fn CppObj_CppObj(this: *mut CppObj, x: ::std::os::raw::c_int); +} +unsafe extern "C" { + #[link_name = "\u{1}??1CppObj@@QEAA@XZ"] + pub fn CppObj_CppObj_destructor(this: *mut CppObj); +} +impl CppObj { + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + CppObj_CppObj(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } + #[inline] + pub unsafe fn destruct(&mut self) { + CppObj_CppObj_destructor(self) + } +} +#[repr(C)] +pub struct CppObj2__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug)] +pub struct CppObj2 { + pub vtable_: *const CppObj2__bindgen_vtable, + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of CppObj2"][::std::mem::size_of::() - 16usize]; + ["Alignment of CppObj2"][::std::mem::align_of::() - 8usize]; + ["Offset of field: CppObj2::x"][::std::mem::offset_of!(CppObj2, x) - 8usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}??0CppObj2@@QEAA@H@Z"] + pub fn CppObj2_CppObj2(this: *mut CppObj2, x: ::std::os::raw::c_int); +} +impl Default for CppObj2 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl CppObj2 { + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + CppObj2_CppObj2(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } +} +unsafe extern "C" { + #[link_name = "\u{1}??1CppObj2@@UEAA@XZ"] + pub fn CppObj2_CppObj2_destructor(this: *mut CppObj2); +} +#[repr(C)] +#[derive(Debug)] +pub struct CppObj3 { + pub _base: CppObj2, + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of CppObj3"][::std::mem::size_of::() - 24usize]; + ["Alignment of CppObj3"][::std::mem::align_of::() - 8usize]; + ["Offset of field: CppObj3::x"][::std::mem::offset_of!(CppObj3, x) - 16usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}??0CppObj3@@QEAA@H@Z"] + pub fn CppObj3_CppObj3(this: *mut CppObj3, x: ::std::os::raw::c_int); +} +impl Default for CppObj3 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl CppObj3 { + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + CppObj3_CppObj3(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } +} +unsafe extern "C" { + #[link_name = "\u{1}??1CppObj3@@UEAA@XZ"] + pub fn CppObj3_CppObj3_destructor(this: *mut CppObj3); +} +#[repr(C)] +#[derive(Debug)] +pub struct CppObj4 { + pub _base: CppObj2, + pub x: ::std::os::raw::c_int, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of CppObj4"][::std::mem::size_of::() - 24usize]; + ["Alignment of CppObj4"][::std::mem::align_of::() - 8usize]; + ["Offset of field: CppObj4::x"][::std::mem::offset_of!(CppObj4, x) - 16usize]; +}; +unsafe extern "C" { + #[link_name = "\u{1}??0CppObj4@@QEAA@H@Z"] + pub fn CppObj4_CppObj4(this: *mut CppObj4, x: ::std::os::raw::c_int); +} +impl Default for CppObj4 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl CppObj4 { + #[inline] + pub unsafe fn new(x: ::std::os::raw::c_int) -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + CppObj4_CppObj4(__bindgen_tmp.as_mut_ptr(), x); + __bindgen_tmp.assume_init() + } +} +unsafe extern "C" { + #[link_name = "\u{1}??1CppObj4@@UEAA@XZ"] + pub fn CppObj4_CppObj4_destructor(this: *mut CppObj4); +} diff --git a/bindgen-tests/tests/expectations/tests/win32-thiscall.rs b/bindgen-tests/tests/expectations/tests/win32-thiscall.rs new file mode 100644 index 0000000000..aecdfbbf1f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-thiscall.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "thiscall" { + #[link_name = "\u{1}?test@Foo@@QAEXXZ"] + pub fn Foo_test(this: *mut Foo); +} +unsafe extern "thiscall" { + #[link_name = "\u{1}?test2@Foo@@QAEHH@Z"] + pub fn Foo_test2( + this: *mut Foo, + var: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn test(&mut self) { + Foo_test(self) + } + #[inline] + pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + Foo_test2(self, var) + } +} diff --git a/bindgen-tests/tests/expectations/tests/win32-thiscall_1_73.rs b/bindgen-tests/tests/expectations/tests/win32-thiscall_1_73.rs new file mode 100644 index 0000000000..4741f029ff --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-thiscall_1_73.rs @@ -0,0 +1,33 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target = "i686-pc-windows-msvc")] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::(), 1usize, "Size of Foo"); + assert_eq!(::std::mem::align_of::(), 1usize, "Alignment of Foo"); +} +extern "thiscall" { + #[link_name = "\u{1}?test@Foo@@QAEXXZ"] + pub fn Foo_test(this: *mut Foo); +} +extern "thiscall" { + #[link_name = "\u{1}?test2@Foo@@QAEHH@Z"] + pub fn Foo_test2( + this: *mut Foo, + var: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn test(&mut self) { + Foo_test(self) + } + #[inline] + pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + Foo_test2(self, var) + } +} diff --git a/bindgen-tests/tests/expectations/tests/win32-thiscall_nightly.rs b/bindgen-tests/tests/expectations/tests/win32-thiscall_nightly.rs new file mode 100644 index 0000000000..87b63574a9 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-thiscall_nightly.rs @@ -0,0 +1,34 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#![feature(abi_thiscall)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Foo"][::std::mem::size_of::() - 1usize]; + ["Alignment of Foo"][::std::mem::align_of::() - 1usize]; +}; +unsafe extern "thiscall" { + #[link_name = "\u{1}?test@Foo@@QAEXXZ"] + pub fn Foo_test(this: *mut Foo); +} +unsafe extern "thiscall" { + #[link_name = "\u{1}?test2@Foo@@QAEHH@Z"] + pub fn Foo_test2( + this: *mut Foo, + var: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +impl Foo { + #[inline] + pub unsafe fn test(&mut self) { + Foo_test(self) + } + #[inline] + pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int { + Foo_test2(self, var) + } +} diff --git a/bindgen-tests/tests/expectations/tests/win32-vectorcall-nightly.rs b/bindgen-tests/tests/expectations/tests/win32-vectorcall-nightly.rs new file mode 100644 index 0000000000..1c7b2fdbf6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-vectorcall-nightly.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(feature = "nightly")] +#![feature(abi_vectorcall)] +unsafe extern "vectorcall" { + #[link_name = "\u{1}test_vectorcall@@16"] + pub fn test_vectorcall( + a: ::std::os::raw::c_int, + b: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} diff --git a/bindgen-tests/tests/expectations/tests/win32-vectorcall.rs b/bindgen-tests/tests/expectations/tests/win32-vectorcall.rs new file mode 100644 index 0000000000..fe64295a68 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/win32-vectorcall.rs @@ -0,0 +1 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] \ No newline at end of file diff --git a/bindgen-tests/tests/expectations/tests/with_array_pointers_arguments.rs b/bindgen-tests/tests/expectations/tests/with_array_pointers_arguments.rs new file mode 100644 index 0000000000..7cc1d65daf --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/with_array_pointers_arguments.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn test_fn( + a: f32, + arr: *mut [::std::os::raw::c_int; 20usize], + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn test_fn2( + arr: *const [f32; 20usize], + b: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +pub type defArr = [::std::os::raw::c_char; 20usize]; +pub type foo = ::std::option::Option; +unsafe extern "C" { + pub fn bar(a: *mut defArr); +} diff --git a/bindgen-tests/tests/expectations/tests/without_array_pointers_arguments.rs b/bindgen-tests/tests/expectations/tests/without_array_pointers_arguments.rs new file mode 100644 index 0000000000..d642e84d27 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/without_array_pointers_arguments.rs @@ -0,0 +1,14 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + pub fn test_fn(a: f32, arr: *mut ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + pub fn test_fn2(arr: *const f32, b: ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +pub type defArr = [::std::os::raw::c_char; 20usize]; +pub type foo = ::std::option::Option< + unsafe extern "C" fn(a: *mut ::std::os::raw::c_char), +>; +unsafe extern "C" { + pub fn bar(a: *mut ::std::os::raw::c_char); +} diff --git a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs new file mode 100644 index 0000000000..bafcad8a7e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs @@ -0,0 +1,91 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "foo__extern"] + pub fn foo() -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "bar__extern"] + pub fn bar() -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "takes_ptr__extern"] + pub fn takes_ptr(arg: *mut ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "takes_fn_ptr__extern"] + pub fn takes_fn_ptr( + f: ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, + >, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "takes_fn__extern"] + pub fn takes_fn( + f: ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, + >, + ) -> ::std::os::raw::c_int; +} +pub type func = ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, +>; +unsafe extern "C" { + #[link_name = "takes_alias__extern"] + pub fn takes_alias(f: func) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "takes_qualified__extern"] + pub fn takes_qualified( + arg: *const *const ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +pub const foo_BAR: foo = 0; +pub type foo = ::std::os::raw::c_uint; +unsafe extern "C" { + #[link_name = "takes_enum__extern"] + pub fn takes_enum(f: foo) -> foo; +} +unsafe extern "C" { + #[link_name = "nevermore__extern"] + pub fn nevermore(); +} +unsafe extern "C" { + #[link_name = "takes_fn_with_no_args__extern"] + pub fn takes_fn_with_no_args( + f: ::std::option::Option ::std::os::raw::c_int>, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "no_extra_argument__extern"] + pub fn no_extra_argument(va: *mut __va_list_tag); +} +unsafe extern "C" { + #[link_name = "many_va_list__extern"] + pub fn many_va_list( + i: ::std::os::raw::c_int, + va1: *mut __va_list_tag, + va2: *mut __va_list_tag, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "wrap_as_variadic_fn1__extern"] + pub fn wrap_as_variadic_fn1_wrapped( + i: ::std::os::raw::c_int, + ... + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "wrap_as_variadic_fn2__extern"] + pub fn wrap_as_variadic_fn2_wrapped(i: ::std::os::raw::c_int, ...); +} +pub type __builtin_va_list = [__va_list_tag; 1usize]; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __va_list_tag { + pub gp_offset: ::std::os::raw::c_uint, + pub fp_offset: ::std::os::raw::c_uint, + pub overflow_arg_area: *mut ::std::os::raw::c_void, + pub reg_save_area: *mut ::std::os::raw::c_void, + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_anon_union.rs b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_anon_union.rs new file mode 100644 index 0000000000..94bddf4c25 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_anon_union.rs @@ -0,0 +1,57 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct TErrorResult { + pub mResult: ::std::os::raw::c_int, + pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, + pub mMightHaveUnreported: bool, + pub mUnionState: TErrorResult_UnionState, +} +pub const TErrorResult_UnionState_HasMessage: TErrorResult_UnionState = 0; +pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState = 0; +pub type TErrorResult_UnionState = i32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult_Message { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult_DOMExceptionInfo { + _unused: [u8; 0], +} +#[repr(C)] +pub union TErrorResult__bindgen_ty_1 { + pub mMessage: *mut TErrorResult_Message, + pub mDOMExceptionInfo: *mut TErrorResult_DOMExceptionInfo, +} +impl Default for TErrorResult__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl Default for TErrorResult { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +pub struct ErrorResult { + pub _base: TErrorResult, +} +impl Default for ErrorResult { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_class.rs b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_class.rs new file mode 100644 index 0000000000..617a037631 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_class.rs @@ -0,0 +1,209 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + unsafe { ::std::slice::from_raw_parts(self.as_ptr(), len) } + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + unsafe { ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], +} +impl Default for C { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug)] +pub struct C_with_zero_length_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +impl Default for C_with_zero_length_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_zero_length_array_2 { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[repr(C)] +#[derive(Debug)] +pub struct C_with_incomplete_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +impl Default for C_with_incomplete_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_incomplete_array_2 { + pub a: ::std::os::raw::c_int, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[repr(C)] +#[derive(Debug)] +pub struct C_with_zero_length_array_and_incomplete_array { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +impl Default for C_with_zero_length_array_and_incomplete_array { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct C_with_zero_length_array_and_incomplete_array_2 { + pub a: ::std::os::raw::c_int, + pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, + pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct WithDtor { + pub b: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug)] +pub struct IncompleteArrayNonCopiable { + pub whatever: *mut ::std::os::raw::c_void, + pub incomplete_array: __IncompleteArrayField, +} +impl Default for IncompleteArrayNonCopiable { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union Union { + pub d: f32, + pub i: ::std::os::raw::c_int, +} +impl Default for Union { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct WithUnion { + pub data: Union, +} +impl Default for WithUnion { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct RealAbstractionWithTonsOfMethods { + pub _address: u8, +} +unsafe extern "C" { + #[link_name = "\u{1}_ZNK32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar( + this: *const RealAbstractionWithTonsOfMethods, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar1( + this: *mut RealAbstractionWithTonsOfMethods, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEi"] + pub fn RealAbstractionWithTonsOfMethods_bar2( + this: *mut RealAbstractionWithTonsOfMethods, + foo: ::std::os::raw::c_int, + ); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3staEv"] + pub fn RealAbstractionWithTonsOfMethods_sta(); +} +impl RealAbstractionWithTonsOfMethods { + #[inline] + pub unsafe fn bar(&self) { + unsafe { RealAbstractionWithTonsOfMethods_bar(self) } + } + #[inline] + pub unsafe fn bar1(&mut self) { + unsafe { RealAbstractionWithTonsOfMethods_bar1(self) } + } + #[inline] + pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { + unsafe { RealAbstractionWithTonsOfMethods_bar2(self, foo) } + } + #[inline] + pub unsafe fn sta() { + unsafe { RealAbstractionWithTonsOfMethods_sta() } + } +} diff --git a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs new file mode 100644 index 0000000000..05be5d9944 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs @@ -0,0 +1,63 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub struct TestLib { + __library: ::libloading::Library, + pub foo: Result< + unsafe extern "C" fn( + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub bar: Result< + unsafe extern "C" fn(x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub baz: Result< + unsafe extern "C" fn() -> ::std::os::raw::c_int, + ::libloading::Error, + >, + pub FLUX: Result<*mut ::std::os::raw::c_int, ::libloading::Error>, +} +impl TestLib { + pub unsafe fn new

(path: P) -> Result + where + P: AsRef<::std::ffi::OsStr>, + { + let library = unsafe { ::libloading::Library::new(path) }?; + unsafe { Self::from_library(library) } + } + pub unsafe fn from_library(library: L) -> Result + where + L: Into<::libloading::Library>, + { + let __library = library.into(); + let foo = unsafe { __library.get(b"foo\0") }.map(|sym| *sym); + let bar = unsafe { __library.get(b"bar\0") }.map(|sym| *sym); + let baz = unsafe { __library.get(b"baz\0") }.map(|sym| *sym); + let FLUX = unsafe { __library.get::<*mut ::std::os::raw::c_int>(b"FLUX\0") } + .map(|sym| *sym); + Ok(TestLib { + __library, + foo, + bar, + baz, + FLUX, + }) + } + pub unsafe fn foo( + &self, + x: ::std::os::raw::c_int, + y: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int { + unsafe { (self.foo.as_ref().expect("Expected function, got error."))(x, y) } + } + pub unsafe fn bar(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { + unsafe { (self.bar.as_ref().expect("Expected function, got error."))(x) } + } + pub unsafe fn baz(&self) -> ::std::os::raw::c_int { + unsafe { (self.baz.as_ref().expect("Expected function, got error."))() } + } + pub unsafe fn FLUX(&self) -> *mut ::std::os::raw::c_int { + *self.FLUX.as_ref().expect("Expected variable, got error.") + } +} diff --git a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_objc_class.rs b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_objc_class.rs new file mode 100644 index 0000000000..34252b10d3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_objc_class.rs @@ -0,0 +1,32 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(target_os = "macos")] +use objc::{self, msg_send, sel, sel_impl, class}; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +unsafe extern "C" { + pub static mut fooVar: Foo; +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(&self) + where + ::Target: objc::Message + Sized, + { + unsafe { msg_send!(* self, method) } + } +} diff --git a/bindgen-tests/tests/expectations/tests/zero-size-array-align.rs b/bindgen-tests/tests/expectations/tests/zero-size-array-align.rs new file mode 100644 index 0000000000..48fc0cb1d6 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/zero-size-array-align.rs @@ -0,0 +1,50 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct dm_deps { + pub count: ::std::os::raw::c_uint, + pub filler: ::std::os::raw::c_uint, + pub device: __IncompleteArrayField<::std::os::raw::c_ulonglong>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of dm_deps"][::std::mem::size_of::() - 8usize]; + ["Alignment of dm_deps"][::std::mem::align_of::() - 8usize]; + ["Offset of field: dm_deps::count"][::std::mem::offset_of!(dm_deps, count) - 0usize]; + [ + "Offset of field: dm_deps::filler", + ][::std::mem::offset_of!(dm_deps, filler) - 4usize]; + [ + "Offset of field: dm_deps::device", + ][::std::mem::offset_of!(dm_deps, device) - 8usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/zero-sized-array.rs b/bindgen-tests/tests/expectations/tests/zero-sized-array.rs new file mode 100644 index 0000000000..229a6ee4db --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/zero-sized-array.rs @@ -0,0 +1,115 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +/// Bizarrely enough, this should *not* get an `_address` field. +#[repr(C)] +#[derive(Debug, Default)] +pub struct ZeroSizedArray { + pub arr: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ZeroSizedArray"][::std::mem::size_of::() - 0usize]; + ["Alignment of ZeroSizedArray"][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ZeroSizedArray::arr", + ][::std::mem::offset_of!(ZeroSizedArray, arr) - 0usize]; +}; +/// And nor should this get an `_address` field. +#[repr(C)] +#[derive(Debug, Default)] +pub struct ContainsZeroSizedArray { + pub zsa: ZeroSizedArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsZeroSizedArray", + ][::std::mem::size_of::() - 0usize]; + [ + "Alignment of ContainsZeroSizedArray", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ContainsZeroSizedArray::zsa", + ][::std::mem::offset_of!(ContainsZeroSizedArray, zsa) - 0usize]; +}; +/** Inheriting from ZeroSizedArray shouldn't cause an `_address` to be inserted + either.*/ +#[repr(C)] +#[derive(Debug, Default)] +pub struct InheritsZeroSizedArray { + pub _base: ZeroSizedArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of InheritsZeroSizedArray", + ][::std::mem::size_of::() - 0usize]; + [ + "Alignment of InheritsZeroSizedArray", + ][::std::mem::align_of::() - 1usize]; +}; +/// And this should not get an `_address` field either. +#[repr(C)] +#[derive(Debug, Default)] +pub struct DynamicallySizedArray { + pub arr: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of DynamicallySizedArray", + ][::std::mem::size_of::() - 0usize]; + [ + "Alignment of DynamicallySizedArray", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: DynamicallySizedArray::arr", + ][::std::mem::offset_of!(DynamicallySizedArray, arr) - 0usize]; +}; +/// No `_address` field here either. +#[repr(C)] +#[derive(Debug, Default)] +pub struct ContainsDynamicallySizedArray { + pub dsa: DynamicallySizedArray, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + [ + "Size of ContainsDynamicallySizedArray", + ][::std::mem::size_of::() - 0usize]; + [ + "Alignment of ContainsDynamicallySizedArray", + ][::std::mem::align_of::() - 1usize]; + [ + "Offset of field: ContainsDynamicallySizedArray::dsa", + ][::std::mem::offset_of!(ContainsDynamicallySizedArray, dsa) - 0usize]; +}; diff --git a/tests/headers/16-byte-alignment.h b/bindgen-tests/tests/headers/16-byte-alignment.h similarity index 100% rename from tests/headers/16-byte-alignment.h rename to bindgen-tests/tests/headers/16-byte-alignment.h diff --git a/tests/headers/381-decltype-alias.hpp b/bindgen-tests/tests/headers/381-decltype-alias.hpp similarity index 100% rename from tests/headers/381-decltype-alias.hpp rename to bindgen-tests/tests/headers/381-decltype-alias.hpp diff --git a/bindgen-tests/tests/headers/abi-override.h b/bindgen-tests/tests/headers/abi-override.h new file mode 100644 index 0000000000..0b0fdcf245 --- /dev/null +++ b/bindgen-tests/tests/headers/abi-override.h @@ -0,0 +1,9 @@ +// bindgen-flags: --override-abi=foo=fastcall --override-abi=bar=stdcall --override-abi=boo=efiapi --override-abi=foobar=efiapi --override-abi qux=system --raw-line '#![cfg(target = "i686-pc-windows-msvc")]' + +void foo(); +void bar(); +void baz(); +void qux(); + +typedef void (*boo)(); +typedef void (*foobar)(boo boo); diff --git a/bindgen-tests/tests/headers/abi_variadic_function.hpp b/bindgen-tests/tests/headers/abi_variadic_function.hpp new file mode 100644 index 0000000000..2141535c7a --- /dev/null +++ b/bindgen-tests/tests/headers/abi_variadic_function.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: -- -std=c++11 + +char __attribute__((ms_abi)) a(char, ...); +char b(char, ...); diff --git a/tests/headers/accessors.hpp b/bindgen-tests/tests/headers/accessors.hpp similarity index 100% rename from tests/headers/accessors.hpp rename to bindgen-tests/tests/headers/accessors.hpp diff --git a/bindgen-tests/tests/headers/alias_comments.h b/bindgen-tests/tests/headers/alias_comments.h new file mode 100644 index 0000000000..2547c3c1a2 --- /dev/null +++ b/bindgen-tests/tests/headers/alias_comments.h @@ -0,0 +1,26 @@ +// bindgen-flags: --no-layout-tests + +/** + * This is Struct + */ +typedef struct { + /** + * This is field + */ + int field; +} Struct; + +/** + * This is AliasToStruct + */ +typedef Struct AliasToStruct; + +/** + * This is AliasToInt + */ +typedef int AliasToInt; + +/** + * This is AliasToAliasToInt + */ +typedef AliasToInt AliasToAliasToInt; diff --git a/bindgen-tests/tests/headers/allowlist-file.hpp b/bindgen-tests/tests/headers/allowlist-file.hpp new file mode 100644 index 0000000000..b0354a047f --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist-file.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --allowlist-file ".*/allowlisted/file.*" --allowlist-type AllowlistMe -- -Itests/headers + + +// Forward declaration of struct that's defined in an allowlisted file. +struct StructWithAllowlistedDefinition; + +#include "allowlisted/file.hpp" + +// Actual definition of struct that has a forward declaration in an allowlisted file. +struct StructWithAllowlistedFwdDecl { + int b; +}; + +class Ignored { + char c; +}; + +// Also have an explicitly allowlisted type +class AllowlistMe { + int foo; +}; diff --git a/bindgen-tests/tests/headers/allowlist-namespaces-basic.hpp b/bindgen-tests/tests/headers/allowlist-namespaces-basic.hpp new file mode 100644 index 0000000000..fb4dd1be37 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist-namespaces-basic.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type outer::inner::Helper + +namespace outer { + namespace inner { + struct Helper {}; + } + struct Test { + inner::Helper helper; + }; +} diff --git a/bindgen-tests/tests/headers/allowlist-namespaces.hpp b/bindgen-tests/tests/headers/allowlist-namespaces.hpp new file mode 100644 index 0000000000..2cffe9d3dd --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist-namespaces.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type '.*' + +namespace outer { + namespace inner { + struct Helper {}; + } + struct Test { + inner::Helper helper; + }; +} diff --git a/bindgen-tests/tests/headers/allowlist_basic.hpp b/bindgen-tests/tests/headers/allowlist_basic.hpp new file mode 100644 index 0000000000..ef858c95da --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist_basic.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: --allowlist-type AllowlistMe + +template +class AllowlistMe { + class Inner { + T bar; + }; + + int foo; + Inner bar; +}; + +struct DontAllowlistMe { + void* foo; + double _Complex noComplexGenerated; +}; diff --git a/bindgen-tests/tests/headers/allowlist_fix.hpp b/bindgen-tests/tests/headers/allowlist_fix.hpp new file mode 100644 index 0000000000..ff810fc6e0 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist_fix.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --allowlist-function 'Servo_.*' --blocklist-type Test --raw-line "pub enum Test {}" + +struct Test {}; +extern "C" void Servo_Test(Test* a); diff --git a/bindgen-tests/tests/headers/allowlist_item.h b/bindgen-tests/tests/headers/allowlist_item.h new file mode 100644 index 0000000000..7e5e00d0e3 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist_item.h @@ -0,0 +1,17 @@ +// bindgen-flags: --allowlist-item 'Foo.*' + +struct Foo { + int field; +}; + +struct Foo FooNew(int value); + +#define FooDefault 0 + +struct Bar { + int field; +}; + +struct Foo BarNew(int value); + +#define BarDefault 0 diff --git a/tests/headers/whitelist_vars.h b/bindgen-tests/tests/headers/allowlist_vars.h similarity index 100% rename from tests/headers/whitelist_vars.h rename to bindgen-tests/tests/headers/allowlist_vars.h diff --git a/bindgen-tests/tests/headers/allowlist_warnings.h b/bindgen-tests/tests/headers/allowlist_warnings.h new file mode 100644 index 0000000000..83c9e259f0 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlist_warnings.h @@ -0,0 +1,2 @@ +// bindgen-flags: --allowlist-function "doesnt_match_anything" +int non_matched_function(int arg); diff --git a/bindgen-tests/tests/headers/allowlisted-item-references-no-hash.hpp b/bindgen-tests/tests/headers/allowlisted-item-references-no-hash.hpp new file mode 100644 index 0000000000..56c2a39fba --- /dev/null +++ b/bindgen-tests/tests/headers/allowlisted-item-references-no-hash.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --with-derive-hash --allowlist-type "AllowlistMe" --no-hash "NoHash" + +struct NoHash {}; + +class AllowlistMe { + NoHash a; +}; diff --git a/bindgen-tests/tests/headers/allowlisted-item-references-no-partialeq.hpp b/bindgen-tests/tests/headers/allowlisted-item-references-no-partialeq.hpp new file mode 100644 index 0000000000..d85fb6b754 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlisted-item-references-no-partialeq.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --with-derive-partialeq --allowlist-type "AllowlistMe" --no-partialeq "NoPartialEq" + +struct NoPartialEq {}; + +class AllowlistMe { + NoPartialEq a; +}; diff --git a/bindgen-tests/tests/headers/allowlisted/file.hpp b/bindgen-tests/tests/headers/allowlisted/file.hpp new file mode 100644 index 0000000000..5f360e5ea9 --- /dev/null +++ b/bindgen-tests/tests/headers/allowlisted/file.hpp @@ -0,0 +1,22 @@ +void SomeFunction(); +extern int someVar; +#define SOME_DEFUN 123 + +class someClass { + void somePrivateMethod(); +public: + void somePublicMethod(int foo); +}; + +extern "C" void ExternFunction(); + +namespace foo { + void NamespacedFunction(); +} + + +struct StructWithAllowlistedFwdDecl; + +struct StructWithAllowlistedDefinition { + StructWithAllowlistedFwdDecl* other; +}; diff --git a/bindgen-tests/tests/headers/allowlisted_item_references_no_copy.hpp b/bindgen-tests/tests/headers/allowlisted_item_references_no_copy.hpp new file mode 100644 index 0000000000..9feb30549a --- /dev/null +++ b/bindgen-tests/tests/headers/allowlisted_item_references_no_copy.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --allowlist-type "AllowlistMe" --no-copy "NoCopy" + +struct NoCopy {}; + +class AllowlistMe { + NoCopy a; +}; diff --git a/tests/headers/annotation_hide.hpp b/bindgen-tests/tests/headers/annotation_hide.hpp similarity index 100% rename from tests/headers/annotation_hide.hpp rename to bindgen-tests/tests/headers/annotation_hide.hpp diff --git a/bindgen-tests/tests/headers/anon-fields-prefix.h b/bindgen-tests/tests/headers/anon-fields-prefix.h new file mode 100644 index 0000000000..8dcae0c61a --- /dev/null +++ b/bindgen-tests/tests/headers/anon-fields-prefix.h @@ -0,0 +1,15 @@ +// bindgen-flags: --anon-fields-prefix "u" + +union color { + struct { + unsigned char r; + unsigned char g; + unsigned char b; + }; + struct { + unsigned char y; + unsigned char u; + unsigned char v; + }; + unsigned char v3[3]; +}; diff --git a/tests/headers/anon_enum.hpp b/bindgen-tests/tests/headers/anon_enum.hpp similarity index 81% rename from tests/headers/anon_enum.hpp rename to bindgen-tests/tests/headers/anon_enum.hpp index 23dc5ceb8f..bbd52240a7 100644 --- a/tests/headers/anon_enum.hpp +++ b/bindgen-tests/tests/headers/anon_enum.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" struct Test { int foo; float bar; diff --git a/bindgen-tests/tests/headers/anon_enum_allowlist.h b/bindgen-tests/tests/headers/anon_enum_allowlist.h new file mode 100644 index 0000000000..94119a8773 --- /dev/null +++ b/bindgen-tests/tests/headers/anon_enum_allowlist.h @@ -0,0 +1,6 @@ +// bindgen-flags: --allowlist-var "NODE_.*" --rustified-enum ".*" + +enum { + NODE_FLAG_FOO, + NODE_FLAG_BAR, +}; diff --git a/bindgen-tests/tests/headers/anon_enum_allowlist_item.h b/bindgen-tests/tests/headers/anon_enum_allowlist_item.h new file mode 100644 index 0000000000..23caacc9a1 --- /dev/null +++ b/bindgen-tests/tests/headers/anon_enum_allowlist_item.h @@ -0,0 +1,6 @@ +// bindgen-flags: --allowlist-item "NODE_.*" + +enum { + NODE_FLAG_FOO, + NODE_FLAG_BAR, +}; diff --git a/bindgen-tests/tests/headers/anon_enum_blocklist.h b/bindgen-tests/tests/headers/anon_enum_blocklist.h new file mode 100644 index 0000000000..61aa6e680c --- /dev/null +++ b/bindgen-tests/tests/headers/anon_enum_blocklist.h @@ -0,0 +1,11 @@ +// bindgen-flags: --blocklist-type "_bindgen_ty_1" + +enum { + FLAG_X, + FLAG_Y, +}; + +enum { + FLAG_Z, + FLAG_W, +}; diff --git a/tests/headers/anon_enum_trait.hpp b/bindgen-tests/tests/headers/anon_enum_trait.hpp similarity index 92% rename from tests/headers/anon_enum_trait.hpp rename to bindgen-tests/tests/headers/anon_enum_trait.hpp index 6383c74892..cc0cd3898c 100644 --- a/tests/headers/anon_enum_trait.hpp +++ b/bindgen-tests/tests/headers/anon_enum_trait.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" template class DataType { diff --git a/tests/headers/anon_struct_in_union.h b/bindgen-tests/tests/headers/anon_struct_in_union.h similarity index 100% rename from tests/headers/anon_struct_in_union.h rename to bindgen-tests/tests/headers/anon_struct_in_union.h diff --git a/tests/headers/anon_union.hpp b/bindgen-tests/tests/headers/anon_union.hpp similarity index 92% rename from tests/headers/anon_union.hpp rename to bindgen-tests/tests/headers/anon_union.hpp index 19c478d18c..e4be25bcab 100644 --- a/tests/headers/anon_union.hpp +++ b/bindgen-tests/tests/headers/anon_union.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" template struct TErrorResult { enum UnionState { diff --git a/tests/headers/anonymous-template-types.hpp b/bindgen-tests/tests/headers/anonymous-template-types.hpp similarity index 100% rename from tests/headers/anonymous-template-types.hpp rename to bindgen-tests/tests/headers/anonymous-template-types.hpp diff --git a/tests/headers/arg_keyword.hpp b/bindgen-tests/tests/headers/arg_keyword.hpp similarity index 100% rename from tests/headers/arg_keyword.hpp rename to bindgen-tests/tests/headers/arg_keyword.hpp diff --git a/tests/headers/array-of-zero-sized-types.hpp b/bindgen-tests/tests/headers/array-of-zero-sized-types.hpp similarity index 100% rename from tests/headers/array-of-zero-sized-types.hpp rename to bindgen-tests/tests/headers/array-of-zero-sized-types.hpp diff --git a/bindgen-tests/tests/headers/atomic-constant.h b/bindgen-tests/tests/headers/atomic-constant.h new file mode 100644 index 0000000000..b28f76f7e4 --- /dev/null +++ b/bindgen-tests/tests/headers/atomic-constant.h @@ -0,0 +1,2 @@ +_Atomic(int) a; +int b; diff --git a/bindgen-tests/tests/headers/attribute-custom-cli.h b/bindgen-tests/tests/headers/attribute-custom-cli.h new file mode 100644 index 0000000000..a5f73c78e5 --- /dev/null +++ b/bindgen-tests/tests/headers/attribute-custom-cli.h @@ -0,0 +1,14 @@ +// bindgen-flags: --default-enum-style rust --default-non-copy-union-style manually_drop --no-default=".*" --no-hash=".*" --no-partialeq=".*" --no-debug=".*" --no-copy=".*" --with-attribute-custom="foo_[^e].*=#[doc(hidden)]" --with-attribute-custom-struct="foo.*=#[derive(Default)]" --with-attribute-custom-enum="foo.*=#[cfg_attr(test, derive(PartialOrd, Copy))]" --with-attribute-custom-union="foo.*=#[derive(Clone)],#[derive(Copy)]" +struct foo_struct { + int inner; +}; +enum foo_enum { + inner = 0 +}; +union foo_union { + int fst; + float snd; +}; +struct non_matching { + int inner; +}; diff --git a/bindgen-tests/tests/headers/attribute-custom.h b/bindgen-tests/tests/headers/attribute-custom.h new file mode 100644 index 0000000000..dd382bf8cd --- /dev/null +++ b/bindgen-tests/tests/headers/attribute-custom.h @@ -0,0 +1,28 @@ +// bindgen-flags: --no-derive-debug --no-derive-copy --no-derive-default --default-enum-style rust --no-layout-tests + +/**

*/ +struct my_type; + +/**
*/ +struct my_type; + +struct my_type { + int a; +}; + +/** + *
+ *
+ */ +struct my_type2; + +struct my_type2 { + unsigned a; +}; + +/** + *
+ */ +struct my_type3 { + unsigned long a; +}; diff --git a/bindgen-tests/tests/headers/attribute_warn_unused_result.hpp b/bindgen-tests/tests/headers/attribute_warn_unused_result.hpp new file mode 100644 index 0000000000..bb9c3687e9 --- /dev/null +++ b/bindgen-tests/tests/headers/attribute_warn_unused_result.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --enable-function-attribute-detection + +class Foo { +public: + __attribute__((warn_unused_result)) + int foo(int); +}; + +__attribute__((warn_unused_result)) +int foo(int); diff --git a/bindgen-tests/tests/headers/attribute_warn_unused_result_no_attribute_detection.hpp b/bindgen-tests/tests/headers/attribute_warn_unused_result_no_attribute_detection.hpp new file mode 100644 index 0000000000..25127d9cd0 --- /dev/null +++ b/bindgen-tests/tests/headers/attribute_warn_unused_result_no_attribute_detection.hpp @@ -0,0 +1,8 @@ +class Foo { +public: + __attribute__((warn_unused_result)) + int foo(int); +}; + +__attribute__((warn_unused_result)) +int foo(int); diff --git a/tests/headers/auto.hpp b/bindgen-tests/tests/headers/auto.hpp similarity index 100% rename from tests/headers/auto.hpp rename to bindgen-tests/tests/headers/auto.hpp diff --git a/tests/headers/bad-namespace-parenthood-inheritance.hpp b/bindgen-tests/tests/headers/bad-namespace-parenthood-inheritance.hpp similarity index 100% rename from tests/headers/bad-namespace-parenthood-inheritance.hpp rename to bindgen-tests/tests/headers/bad-namespace-parenthood-inheritance.hpp diff --git a/tests/headers/base-to-derived.hpp b/bindgen-tests/tests/headers/base-to-derived.hpp similarity index 100% rename from tests/headers/base-to-derived.hpp rename to bindgen-tests/tests/headers/base-to-derived.hpp diff --git a/bindgen-tests/tests/headers/bindgen-union-inside-namespace.hpp b/bindgen-tests/tests/headers/bindgen-union-inside-namespace.hpp new file mode 100644 index 0000000000..4007e02566 --- /dev/null +++ b/bindgen-tests/tests/headers/bindgen-union-inside-namespace.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --enable-cxx-namespaces + +namespace foo { + union Bar { + int foo; + int bar; + }; +} diff --git a/tests/headers/bitfield-32bit-overflow.h b/bindgen-tests/tests/headers/bitfield-32bit-overflow.h similarity index 100% rename from tests/headers/bitfield-32bit-overflow.h rename to bindgen-tests/tests/headers/bitfield-32bit-overflow.h diff --git a/tests/headers/bitfield-enum-basic.hpp b/bindgen-tests/tests/headers/bitfield-enum-basic.hpp similarity index 92% rename from tests/headers/bitfield-enum-basic.hpp rename to bindgen-tests/tests/headers/bitfield-enum-basic.hpp index c03f0e708a..339fb4d554 100644 --- a/tests/headers/bitfield-enum-basic.hpp +++ b/bindgen-tests/tests/headers/bitfield-enum-basic.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --bitfield-enum "Foo|Buz|NS_.*|DUMMY_.*" --rustified-enum .* -- -std=c++11 +// bindgen-flags: --bitfield-enum "Foo|Buz|NS_.*|DUMMY_.*" --rustified-enum ".*" -- -std=c++11 enum Foo { Bar = 1 << 1, diff --git a/bindgen-tests/tests/headers/bitfield-enum-repr-c.hpp b/bindgen-tests/tests/headers/bitfield-enum-repr-c.hpp new file mode 100644 index 0000000000..da5fc961dd --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield-enum-repr-c.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --bitfield-enum "Foo" -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; diff --git a/bindgen-tests/tests/headers/bitfield-enum-repr-transparent.hpp b/bindgen-tests/tests/headers/bitfield-enum-repr-transparent.hpp new file mode 100644 index 0000000000..1c58ff4eca --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield-enum-repr-transparent.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --bitfield-enum "Foo" + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; diff --git a/tests/headers/bitfield-large.hpp b/bindgen-tests/tests/headers/bitfield-large.hpp similarity index 100% rename from tests/headers/bitfield-large.hpp rename to bindgen-tests/tests/headers/bitfield-large.hpp diff --git a/bindgen-tests/tests/headers/bitfield-linux-32.hpp b/bindgen-tests/tests/headers/bitfield-linux-32.hpp new file mode 100644 index 0000000000..71ee6a7e1d --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield-linux-32.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --no-layout-tests -- --target=i586-unknown-linux + +typedef unsigned long long uint64_t; + +struct Test { + uint64_t foo; + uint64_t x : 56; + uint64_t y : 8; +}; diff --git a/tests/headers/bitfield-method-same-name.hpp b/bindgen-tests/tests/headers/bitfield-method-same-name.hpp similarity index 100% rename from tests/headers/bitfield-method-same-name.hpp rename to bindgen-tests/tests/headers/bitfield-method-same-name.hpp diff --git a/bindgen-tests/tests/headers/bitfield-template.hpp b/bindgen-tests/tests/headers/bitfield-template.hpp new file mode 100644 index 0000000000..664199b9c0 --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield-template.hpp @@ -0,0 +1,4 @@ +template struct foo { + T member; + bool b : 8; +}; diff --git a/tests/headers/bitfield_align.h b/bindgen-tests/tests/headers/bitfield_align.h similarity index 100% rename from tests/headers/bitfield_align.h rename to bindgen-tests/tests/headers/bitfield_align.h diff --git a/bindgen-tests/tests/headers/bitfield_align_2.h b/bindgen-tests/tests/headers/bitfield_align_2.h new file mode 100644 index 0000000000..cb0f2e20d2 --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield_align_2.h @@ -0,0 +1,12 @@ +// bindgen-flags: --rustified-enum ".*" --raw-line '#![cfg(not(target_os="windows"))]' +enum MyEnum { + ONE, + TWO, + THREE, + FOUR +}; + +struct TaggedPtr { + enum MyEnum tag : 2; + long ptr : 62; +}; diff --git a/tests/headers/bitfield_large_overflow.hpp b/bindgen-tests/tests/headers/bitfield_large_overflow.hpp similarity index 100% rename from tests/headers/bitfield_large_overflow.hpp rename to bindgen-tests/tests/headers/bitfield_large_overflow.hpp diff --git a/tests/headers/bitfield_method_mangling.h b/bindgen-tests/tests/headers/bitfield_method_mangling.h similarity index 100% rename from tests/headers/bitfield_method_mangling.h rename to bindgen-tests/tests/headers/bitfield_method_mangling.h diff --git a/bindgen-tests/tests/headers/bitfield_pack_offset.h b/bindgen-tests/tests/headers/bitfield_pack_offset.h new file mode 100644 index 0000000000..5118a64642 --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield_pack_offset.h @@ -0,0 +1,21 @@ +struct A { + const unsigned char name[7]; /* 0 7 */ + unsigned char firmness:4; /* 7: 0 1 */ + unsigned char color:4; /* 7: 4 1 */ + unsigned short weedsBonus:3; /* 8: 0 2 */ + unsigned short pestsBonus:3; /* 8: 3 2 */ + unsigned short size:10; /* 8: 6 2 */ + unsigned char maxYield; /* 10 1 */ + unsigned char minYield:4; /* 11: 0 1 */ + unsigned char waterBonus:4; /* 11: 4 1 */ + + /* XXX 4 bytes hole, try to pack */ + + const unsigned char * description1; /* 16 8 */ + + /* size: 24, cachelines: 1, members: 10 */ + /* sum members: 16, holes: 1, sum holes: 4 */ + /* sum bitfield members: 32 bits (4 bytes) */ + /* last cacheline: 24 bytes */ +}; + diff --git a/bindgen-tests/tests/headers/bitfield_pragma_packed.h b/bindgen-tests/tests/headers/bitfield_pragma_packed.h new file mode 100644 index 0000000000..c18b80ddfc --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield_pragma_packed.h @@ -0,0 +1,20 @@ +#pragma pack(push, 1) +struct Struct { + unsigned char a : 1; + unsigned char b : 1; + unsigned char c : 6; + unsigned short int d : 16; + unsigned char e : 8; +}; +#pragma pack(pop) + +struct Inner { + unsigned short a: 16; + unsigned short b: 16; +}; + +#pragma pack(push, 1) +struct Outer { + struct Inner inner; +}; +#pragma pop diff --git a/bindgen-tests/tests/headers/block_return_type.h b/bindgen-tests/tests/headers/block_return_type.h new file mode 100644 index 0000000000..be76cb5956 --- /dev/null +++ b/bindgen-tests/tests/headers/block_return_type.h @@ -0,0 +1,4 @@ +// bindgen-flags: --generate-block --block-extern-crate -- -fblocks +// bindgen-osx-only + +int (^func(void))(int, int); diff --git a/bindgen-tests/tests/headers/blocklist-and-impl-debug.hpp b/bindgen-tests/tests/headers/blocklist-and-impl-debug.hpp new file mode 100644 index 0000000000..14e17537e1 --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-and-impl-debug.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --impl-debug --blocklist-type BlocklistMe --raw-line 'pub struct BlocklistMe(u8);' + +struct BlocklistMe {}; + +/** + * Because this type contains a blocklisted type, it should not derive Debug. + */ +struct ShouldManuallyImplDebug { + BlocklistMe a; +}; diff --git a/bindgen-tests/tests/headers/blocklist-file.hpp b/bindgen-tests/tests/headers/blocklist-file.hpp new file mode 100644 index 0000000000..ad8bcd665c --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-file.hpp @@ -0,0 +1,18 @@ +// bindgen-flags: --blocklist-file ".*/blocklisted/file.*" -- -Itests/headers + +// Forward declaration of struct that's defined in a blocklisted file. +struct StructWithBlocklistedDefinition; + +#include "blocklisted/file.hpp" +#include "blocklisted/fake-stdint.h" + +struct SizedIntegers { + uint8_t x; + uint16_t y; + uint32_t z; +}; + +// Actual definition of struct that has a forward declaration in a blocklisted file. +struct StructWithBlocklistedFwdDecl { + uint8_t b; +}; diff --git a/bindgen-tests/tests/headers/blocklist-function.hpp b/bindgen-tests/tests/headers/blocklist-function.hpp new file mode 100644 index 0000000000..d7c8bb35d7 --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-function.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: --blocklist-function "ExternFunction" --blocklist-function "foo::NamespacedFunction" --blocklist-function "C_ClassMethod" --enable-cxx-namespaces + +extern "C" void ExternFunction(); + +namespace foo { + void NamespacedFunction(); +} + +namespace bar { + void NamespacedFunction(); +} + +class C { +public: + void ClassMethod(); +}; diff --git a/bindgen-tests/tests/headers/blocklist-item.hpp b/bindgen-tests/tests/headers/blocklist-item.hpp new file mode 100644 index 0000000000..2d795d5a5a --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-item.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --blocklist-item "SomeFunction" --blocklist-item "SOME_DEFUN" --blocklist-item "someVar" --blocklist-item "ExternFunction" --blocklist-item "foo::NamespacedFunction" --blocklist-item "someClass.*" --enable-cxx-namespaces + +void SomeFunction(); +extern int someVar; +#define SOME_DEFUN 123 + +class someClass { + void somePrivateMethod(); +public: + void somePublicMethod(int foo); +}; + +extern "C" void ExternFunction(); + +namespace foo { + void NamespacedFunction(); +} + +namespace bar { + void NamespacedFunction(); +} diff --git a/bindgen-tests/tests/headers/blocklist-methods.hpp b/bindgen-tests/tests/headers/blocklist-methods.hpp new file mode 100644 index 0000000000..4be21b945e --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-methods.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --blocklist-function="Foo_ba.*" + +class Foo { + public: + int foo(); + int bar(); + int baz(); +}; diff --git a/bindgen-tests/tests/headers/blocklist-var.hpp b/bindgen-tests/tests/headers/blocklist-var.hpp new file mode 100644 index 0000000000..3c70e6f032 --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist-var.hpp @@ -0,0 +1,3 @@ +// bindgen-flags: --blocklist-var should_be_blocked + +extern int should_be_blocked; diff --git a/bindgen-tests/tests/headers/blocklist_bitfield_unit.h b/bindgen-tests/tests/headers/blocklist_bitfield_unit.h new file mode 100644 index 0000000000..5f7d94ced9 --- /dev/null +++ b/bindgen-tests/tests/headers/blocklist_bitfield_unit.h @@ -0,0 +1,7 @@ +// bindgen-flags: --blocklist-type "__BindgenBitfieldUnit" --raw-line '#[path = "./struct_with_bitfields.rs"] mod bitfields;' --raw-line 'use bitfields::*;' +struct C { + unsigned char x; + unsigned b1 : 1; + unsigned b2 : 1; + unsigned baz; +}; diff --git a/bindgen-tests/tests/headers/blocklisted/fake-stdint.h b/bindgen-tests/tests/headers/blocklisted/fake-stdint.h new file mode 100644 index 0000000000..a8cfe01056 --- /dev/null +++ b/bindgen-tests/tests/headers/blocklisted/fake-stdint.h @@ -0,0 +1,7 @@ +// -like types get special treatment even when blocklisted. +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; diff --git a/bindgen-tests/tests/headers/blocklisted/file.hpp b/bindgen-tests/tests/headers/blocklisted/file.hpp new file mode 100644 index 0000000000..4bcb589e1d --- /dev/null +++ b/bindgen-tests/tests/headers/blocklisted/file.hpp @@ -0,0 +1,26 @@ +void SomeFunction(); +extern int someVar; +#define SOME_DEFUN 123 + +class someClass { + void somePrivateMethod(); +public: + void somePublicMethod(int foo); +}; + +extern "C" void ExternFunction(); + +namespace foo { + void NamespacedFunction(); +} + +namespace bar { + void NamespacedFunction(); +} + + +struct StructWithBlocklistedFwdDecl; + +struct StructWithBlocklistedDefinition { + StructWithBlocklistedFwdDecl* other; +}; diff --git a/bindgen-tests/tests/headers/blocks-signature.hpp b/bindgen-tests/tests/headers/blocks-signature.hpp new file mode 100644 index 0000000000..eaa72526c2 --- /dev/null +++ b/bindgen-tests/tests/headers/blocks-signature.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --generate-block --block-extern-crate -- -fblocks +// bindgen-osx-only + +#include "blocks.hpp" diff --git a/bindgen-tests/tests/headers/blocks.hpp b/bindgen-tests/tests/headers/blocks.hpp new file mode 100644 index 0000000000..a68de7e2cc --- /dev/null +++ b/bindgen-tests/tests/headers/blocks.hpp @@ -0,0 +1,25 @@ +// bindgen-flags: --block-extern-crate -- -fblocks +// bindgen-osx-only + +typedef unsigned long long size_t; + +void atexit_b(void (^)(void)); + +typedef void *dispatch_data_t; + +typedef bool (^dispatch_data_applier_t)(dispatch_data_t region, + size_t offset, + const void *buffer, + size_t size); + +bool dispatch_data_apply(dispatch_data_t data, + dispatch_data_applier_t applier); + +bool foo(void (^)(size_t bar)); + +bool foo_ptr(void (^*)(size_t bar)); + +struct contains_block_pointers { + void (^val)(int); + void (^*ptr_val)(int); +}; diff --git a/bindgen-tests/tests/headers/bug-1529681.hpp b/bindgen-tests/tests/headers/bug-1529681.hpp new file mode 100644 index 0000000000..17fa849a15 --- /dev/null +++ b/bindgen-tests/tests/headers/bug-1529681.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: -- -std=c++14 +// +// https://bugzilla.mozilla.org/show_bug.cgi?id=1529681 +// https://bugs.llvm.org/show_bug.cgi?id=40813 + +class BrowsingContext { + auto Tie(void* aUnused) const; +}; diff --git a/tests/headers/builtin-template.hpp b/bindgen-tests/tests/headers/builtin-template.hpp similarity index 100% rename from tests/headers/builtin-template.hpp rename to bindgen-tests/tests/headers/builtin-template.hpp diff --git a/tests/headers/c-empty-layout.h b/bindgen-tests/tests/headers/c-empty-layout.h similarity index 100% rename from tests/headers/c-empty-layout.h rename to bindgen-tests/tests/headers/c-empty-layout.h diff --git a/bindgen-tests/tests/headers/c-unwind-abi-override.h b/bindgen-tests/tests/headers/c-unwind-abi-override.h new file mode 100644 index 0000000000..591f4b84ff --- /dev/null +++ b/bindgen-tests/tests/headers/c-unwind-abi-override.h @@ -0,0 +1,5 @@ +// bindgen-flags: --override-abi="foo|bar=C-unwind" + +void foo(); +void bar(); +void baz(); diff --git a/bindgen-tests/tests/headers/c_naming.h b/bindgen-tests/tests/headers/c_naming.h new file mode 100644 index 0000000000..fd84c271fa --- /dev/null +++ b/bindgen-tests/tests/headers/c_naming.h @@ -0,0 +1,19 @@ +// bindgen-flags: --c-naming + +typedef const struct a { + int a; +} *a; + +union b { + int a; + int b; +}; +typedef union b b; + +enum c { + A, +}; + +void takes_a(a arg) {} +void takes_b(b arg) {} +void takes_c(enum c arg) {} diff --git a/tests/headers/call-conv-field.h b/bindgen-tests/tests/headers/call-conv-field.h similarity index 100% rename from tests/headers/call-conv-field.h rename to bindgen-tests/tests/headers/call-conv-field.h diff --git a/bindgen-tests/tests/headers/call-conv-typedef.h b/bindgen-tests/tests/headers/call-conv-typedef.h new file mode 100644 index 0000000000..3b911ddae5 --- /dev/null +++ b/bindgen-tests/tests/headers/call-conv-typedef.h @@ -0,0 +1,5 @@ +// bindgen-flags: --raw-line "#![cfg(not(test))]" -- --target=i686-pc-win32 + + +typedef void (__stdcall *void_fn)(); +typedef void_fn (__stdcall *fn)(int id); diff --git a/bindgen-tests/tests/headers/canonical-types.hpp b/bindgen-tests/tests/headers/canonical-types.hpp new file mode 100644 index 0000000000..c8eadd7e5e --- /dev/null +++ b/bindgen-tests/tests/headers/canonical-types.hpp @@ -0,0 +1,51 @@ +// bindgen-flags: -- -std=c++14 + +// Issue #2078. To pick up the definition of `ClassCInnerA`, +// `ty.canonical_type().declaration().definition()` is needed. + +template +class ClassA { +public: + class ClassAInner { + public: + T *x; + }; +}; + +template +class ClassB { +public: + void foo() { + ((D *)0)->quux(); + } +}; + +template +class ClassC { + struct ClassCInnerA; + + struct ClassCInnerB { + ClassCInnerA *cache; + }; + static_assert(sizeof(ClassCInnerB) > 0, ""); + + struct ClassCInnerA { + ClassCInnerB *member; + }; + +public: + class ClassCInnerCRTP : public ClassB::ClassAInner> { + public: + void quux() { + ((typename ClassA::ClassAInner *)0)->x->member; + } + }; +}; + +class ClassD : public ClassB::ClassCInnerCRTP> { +public: + void bar() { + ((ClassC::ClassCInnerCRTP *)0)->foo(); + } +}; + diff --git a/tests/headers/canonical_path_without_namespacing.hpp b/bindgen-tests/tests/headers/canonical_path_without_namespacing.hpp similarity index 100% rename from tests/headers/canonical_path_without_namespacing.hpp rename to bindgen-tests/tests/headers/canonical_path_without_namespacing.hpp diff --git a/tests/headers/char.h b/bindgen-tests/tests/headers/char.h similarity index 100% rename from tests/headers/char.h rename to bindgen-tests/tests/headers/char.h diff --git a/bindgen-tests/tests/headers/char16_t.hpp b/bindgen-tests/tests/headers/char16_t.hpp new file mode 100644 index 0000000000..35e1f16dd3 --- /dev/null +++ b/bindgen-tests/tests/headers/char16_t.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --use-distinct-char16-t --raw-line '#[repr(transparent)] pub struct bindgen_cchar16_t(u16);' -- -x c++ -std=c++14 + +void receive_char16_t(char16_t input) { +} diff --git a/tests/headers/class.hpp b/bindgen-tests/tests/headers/class.hpp similarity index 100% rename from tests/headers/class.hpp rename to bindgen-tests/tests/headers/class.hpp diff --git a/tests/headers/class_nested.hpp b/bindgen-tests/tests/headers/class_nested.hpp similarity index 100% rename from tests/headers/class_nested.hpp rename to bindgen-tests/tests/headers/class_nested.hpp diff --git a/tests/headers/class_no_members.hpp b/bindgen-tests/tests/headers/class_no_members.hpp similarity index 100% rename from tests/headers/class_no_members.hpp rename to bindgen-tests/tests/headers/class_no_members.hpp diff --git a/tests/headers/class_static.hpp b/bindgen-tests/tests/headers/class_static.hpp similarity index 100% rename from tests/headers/class_static.hpp rename to bindgen-tests/tests/headers/class_static.hpp diff --git a/tests/headers/class_static_const.hpp b/bindgen-tests/tests/headers/class_static_const.hpp similarity index 100% rename from tests/headers/class_static_const.hpp rename to bindgen-tests/tests/headers/class_static_const.hpp diff --git a/tests/headers/class_use_as.hpp b/bindgen-tests/tests/headers/class_use_as.hpp similarity index 100% rename from tests/headers/class_use_as.hpp rename to bindgen-tests/tests/headers/class_use_as.hpp diff --git a/tests/headers/class_with_dtor.hpp b/bindgen-tests/tests/headers/class_with_dtor.hpp similarity index 100% rename from tests/headers/class_with_dtor.hpp rename to bindgen-tests/tests/headers/class_with_dtor.hpp diff --git a/bindgen-tests/tests/headers/class_with_enum.hpp b/bindgen-tests/tests/headers/class_with_enum.hpp new file mode 100644 index 0000000000..ebbc2c4049 --- /dev/null +++ b/bindgen-tests/tests/headers/class_with_enum.hpp @@ -0,0 +1,7 @@ +class A { +public: + enum B { + B1, + B2, + }; +}; \ No newline at end of file diff --git a/tests/headers/class_with_inner_struct.hpp b/bindgen-tests/tests/headers/class_with_inner_struct.hpp similarity index 96% rename from tests/headers/class_with_inner_struct.hpp rename to bindgen-tests/tests/headers/class_with_inner_struct.hpp index 66c2bd3f88..fd195fb789 100644 --- a/tests/headers/class_with_inner_struct.hpp +++ b/bindgen-tests/tests/headers/class_with_inner_struct.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" // bindgen-flags: -- -std=c++11 class A { diff --git a/tests/headers/class_with_typedef.hpp b/bindgen-tests/tests/headers/class_with_typedef.hpp similarity index 100% rename from tests/headers/class_with_typedef.hpp rename to bindgen-tests/tests/headers/class_with_typedef.hpp diff --git a/tests/headers/comment-indent.hpp b/bindgen-tests/tests/headers/comment-indent.hpp similarity index 100% rename from tests/headers/comment-indent.hpp rename to bindgen-tests/tests/headers/comment-indent.hpp diff --git a/tests/headers/complex.h b/bindgen-tests/tests/headers/complex.h similarity index 100% rename from tests/headers/complex.h rename to bindgen-tests/tests/headers/complex.h diff --git a/tests/headers/complex_global.h b/bindgen-tests/tests/headers/complex_global.h similarity index 100% rename from tests/headers/complex_global.h rename to bindgen-tests/tests/headers/complex_global.h diff --git a/bindgen-tests/tests/headers/const-const-mut-ptr.h b/bindgen-tests/tests/headers/const-const-mut-ptr.h new file mode 100644 index 0000000000..cc7daf7c1e --- /dev/null +++ b/bindgen-tests/tests/headers/const-const-mut-ptr.h @@ -0,0 +1,3 @@ +struct foo { + const int** const* const* bar; +}; diff --git a/bindgen-tests/tests/headers/const_array.h b/bindgen-tests/tests/headers/const_array.h new file mode 100644 index 0000000000..a337881f52 --- /dev/null +++ b/bindgen-tests/tests/headers/const_array.h @@ -0,0 +1,2 @@ +extern const int foo[1]; +extern int bar[1]; diff --git a/tests/headers/const_array_fn_arg.h b/bindgen-tests/tests/headers/const_array_fn_arg.h similarity index 100% rename from tests/headers/const_array_fn_arg.h rename to bindgen-tests/tests/headers/const_array_fn_arg.h diff --git a/bindgen-tests/tests/headers/const_array_typedef.h b/bindgen-tests/tests/headers/const_array_typedef.h new file mode 100644 index 0000000000..e5379c97ba --- /dev/null +++ b/bindgen-tests/tests/headers/const_array_typedef.h @@ -0,0 +1,13 @@ +typedef struct { + int field; +} strct; + +typedef strct typ[1]; + +extern typ w; +extern strct *x; + +extern const typ y; +extern const strct *z; + +void function(const typ a, const strct *b); diff --git a/tests/headers/const_bool.hpp b/bindgen-tests/tests/headers/const_bool.hpp similarity index 100% rename from tests/headers/const_bool.hpp rename to bindgen-tests/tests/headers/const_bool.hpp diff --git a/bindgen-tests/tests/headers/const_enum_unnamed.hpp b/bindgen-tests/tests/headers/const_enum_unnamed.hpp new file mode 100644 index 0000000000..cee87e6464 --- /dev/null +++ b/bindgen-tests/tests/headers/const_enum_unnamed.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --rustified-enum ".*" + +enum { + FOO_BAR, + FOO_BAZ, +}; + +class Foo { + enum { FOO_BAR = 10 }; +}; diff --git a/bindgen-tests/tests/headers/const_multidim_array_fn_arg.h b/bindgen-tests/tests/headers/const_multidim_array_fn_arg.h new file mode 100644 index 0000000000..784a51fe80 --- /dev/null +++ b/bindgen-tests/tests/headers/const_multidim_array_fn_arg.h @@ -0,0 +1 @@ +void f(const int a[1][1]); diff --git a/tests/headers/const_ptr.hpp b/bindgen-tests/tests/headers/const_ptr.hpp similarity index 100% rename from tests/headers/const_ptr.hpp rename to bindgen-tests/tests/headers/const_ptr.hpp diff --git a/tests/headers/const_resolved_ty.h b/bindgen-tests/tests/headers/const_resolved_ty.h similarity index 100% rename from tests/headers/const_resolved_ty.h rename to bindgen-tests/tests/headers/const_resolved_ty.h diff --git a/tests/headers/const_tparam.hpp b/bindgen-tests/tests/headers/const_tparam.hpp similarity index 100% rename from tests/headers/const_tparam.hpp rename to bindgen-tests/tests/headers/const_tparam.hpp diff --git a/tests/headers/constant-evaluate.h b/bindgen-tests/tests/headers/constant-evaluate.h similarity index 82% rename from tests/headers/constant-evaluate.h rename to bindgen-tests/tests/headers/constant-evaluate.h index ee9cfaa538..812553ed3e 100644 --- a/tests/headers/constant-evaluate.h +++ b/bindgen-tests/tests/headers/constant-evaluate.h @@ -1,5 +1,5 @@ // bindgen-unstable -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" enum { foo = 4, @@ -10,6 +10,7 @@ typedef unsigned long long EasyToOverflow; const EasyToOverflow k = 0x80000000; const EasyToOverflow k_expr = 1ULL << 60; +const EasyToOverflow wow = 1ULL << 31; const long long BAZ = (1 << foo) | bar; const double fuzz = (1 + 50.0f); diff --git a/tests/headers/constant-non-specialized-tp.hpp b/bindgen-tests/tests/headers/constant-non-specialized-tp.hpp similarity index 100% rename from tests/headers/constant-non-specialized-tp.hpp rename to bindgen-tests/tests/headers/constant-non-specialized-tp.hpp diff --git a/bindgen-tests/tests/headers/constified-enum-module-overflow.hpp b/bindgen-tests/tests/headers/constified-enum-module-overflow.hpp new file mode 100644 index 0000000000..d48f2be1b2 --- /dev/null +++ b/bindgen-tests/tests/headers/constified-enum-module-overflow.hpp @@ -0,0 +1,8 @@ +template class B{}; +template class C { +public: + using U = B; +}; +class A : C
{ + U u; +}; diff --git a/tests/headers/constify-all-enums.h b/bindgen-tests/tests/headers/constify-all-enums.h similarity index 100% rename from tests/headers/constify-all-enums.h rename to bindgen-tests/tests/headers/constify-all-enums.h diff --git a/tests/headers/constify-enum.h b/bindgen-tests/tests/headers/constify-enum.h similarity index 89% rename from tests/headers/constify-enum.h rename to bindgen-tests/tests/headers/constify-enum.h index 9a9058d38b..b8e0be3ee7 100644 --- a/tests/headers/constify-enum.h +++ b/bindgen-tests/tests/headers/constify-enum.h @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" enum nsCSSPropertyID { eCSSProperty_a, diff --git a/tests/headers/constify-module-enums-basic.h b/bindgen-tests/tests/headers/constify-module-enums-basic.h similarity index 100% rename from tests/headers/constify-module-enums-basic.h rename to bindgen-tests/tests/headers/constify-module-enums-basic.h diff --git a/tests/headers/constify-module-enums-namespace.hpp b/bindgen-tests/tests/headers/constify-module-enums-namespace.hpp similarity index 100% rename from tests/headers/constify-module-enums-namespace.hpp rename to bindgen-tests/tests/headers/constify-module-enums-namespace.hpp diff --git a/tests/headers/constify-module-enums-shadow-name.h b/bindgen-tests/tests/headers/constify-module-enums-shadow-name.h similarity index 100% rename from tests/headers/constify-module-enums-shadow-name.h rename to bindgen-tests/tests/headers/constify-module-enums-shadow-name.h diff --git a/tests/headers/constify-module-enums-simple-alias.hpp b/bindgen-tests/tests/headers/constify-module-enums-simple-alias.hpp similarity index 100% rename from tests/headers/constify-module-enums-simple-alias.hpp rename to bindgen-tests/tests/headers/constify-module-enums-simple-alias.hpp diff --git a/tests/headers/constify-module-enums-simple-nonamespace.hpp b/bindgen-tests/tests/headers/constify-module-enums-simple-nonamespace.hpp similarity index 100% rename from tests/headers/constify-module-enums-simple-nonamespace.hpp rename to bindgen-tests/tests/headers/constify-module-enums-simple-nonamespace.hpp diff --git a/tests/headers/constify-module-enums-types.hpp b/bindgen-tests/tests/headers/constify-module-enums-types.hpp similarity index 86% rename from tests/headers/constify-module-enums-types.hpp rename to bindgen-tests/tests/headers/constify-module-enums-types.hpp index 2c652499bb..96bed18f4b 100644 --- a/tests/headers/constify-module-enums-types.hpp +++ b/bindgen-tests/tests/headers/constify-module-enums-types.hpp @@ -1,4 +1,10 @@ -// bindgen-flags: --constified-enum-module .* +// bindgen-flags: --constified-enum-module ".*" + +using Uint = unsigned; +enum ExplicitTypeAlias : Uint { + SOME_CONSTANT, + SOME_OTHER_CONSTANT, +}; typedef enum foo { THIS, @@ -75,4 +81,4 @@ class Thing { }; foo func3(Thing arg1); -foo func4(Thing< Thing > arg1); \ No newline at end of file +foo func4(Thing< Thing > arg1); diff --git a/tests/headers/constructor-tp.hpp b/bindgen-tests/tests/headers/constructor-tp.hpp similarity index 91% rename from tests/headers/constructor-tp.hpp rename to bindgen-tests/tests/headers/constructor-tp.hpp index 6e55ea7852..3b5d54071a 100644 --- a/tests/headers/constructor-tp.hpp +++ b/bindgen-tests/tests/headers/constructor-tp.hpp @@ -8,7 +8,7 @@ class Foo { }; template -inline void +void Foo::doBaz() { } @@ -21,6 +21,5 @@ template Foo::Foo() { } -inline Bar::Bar() { } diff --git a/tests/headers/constructors.hpp b/bindgen-tests/tests/headers/constructors.hpp similarity index 80% rename from tests/headers/constructors.hpp rename to bindgen-tests/tests/headers/constructors.hpp index d417488917..2f8d57b00b 100644 --- a/tests/headers/constructors.hpp +++ b/bindgen-tests/tests/headers/constructors.hpp @@ -1,6 +1,6 @@ class TestOverload { - // This one shouldnt' be generated. + // This one shouldn't be generated. TestOverload(); public: TestOverload(int); diff --git a/bindgen-tests/tests/headers/constructors_1_33.hpp b/bindgen-tests/tests/headers/constructors_1_33.hpp new file mode 100644 index 0000000000..b16c8c35a3 --- /dev/null +++ b/bindgen-tests/tests/headers/constructors_1_33.hpp @@ -0,0 +1,14 @@ +class TestOverload { + // This one shouldn't be generated. + TestOverload(); +public: + /// Calling this should use `mem::unintialized()` and not `MaybeUninit()` as only rust 1.36 includes that. + TestOverload(int); + /// Calling this should use `mem::unintialized()` and not `MaybeUninit()` as only rust 1.36 includes that. + TestOverload(double); +}; + +class TestPublicNoArgs { +public: + TestPublicNoArgs(); +}; diff --git a/tests/headers/contains-vs-inherits-zero-sized.hpp b/bindgen-tests/tests/headers/contains-vs-inherits-zero-sized.hpp similarity index 100% rename from tests/headers/contains-vs-inherits-zero-sized.hpp rename to bindgen-tests/tests/headers/contains-vs-inherits-zero-sized.hpp diff --git a/tests/headers/convert-cpp-comment-to-rust.hpp b/bindgen-tests/tests/headers/convert-cpp-comment-to-rust.hpp similarity index 88% rename from tests/headers/convert-cpp-comment-to-rust.hpp rename to bindgen-tests/tests/headers/convert-cpp-comment-to-rust.hpp index 649c236538..f5bbbf58b2 100644 --- a/tests/headers/convert-cpp-comment-to-rust.hpp +++ b/bindgen-tests/tests/headers/convert-cpp-comment-to-rust.hpp @@ -1,4 +1,4 @@ - +// bindgen-flags: --no-layout-tests typedef unsigned mbedtls_mpi_uint; /** diff --git a/tests/headers/convert-floats.h b/bindgen-tests/tests/headers/convert-floats.h similarity index 100% rename from tests/headers/convert-floats.h rename to bindgen-tests/tests/headers/convert-floats.h diff --git a/bindgen-tests/tests/headers/core_ffi_c.h b/bindgen-tests/tests/headers/core_ffi_c.h new file mode 100644 index 0000000000..6df1e2f87a --- /dev/null +++ b/bindgen-tests/tests/headers/core_ffi_c.h @@ -0,0 +1,14 @@ +// bindgen-flags: --use-core --rust-target 1.64 --no-convert-floats +typedef char c_char; +typedef double c_double; +typedef float c_float; +typedef int c_int; +typedef long c_long; +typedef long long c_longlong; +typedef signed char c_schar; +typedef short c_short; +typedef unsigned char c_uchar; +typedef unsigned int c_uint; +typedef unsigned long c_ulong; +typedef unsigned long long c_ulonglong; +typedef unsigned short c_ushort; diff --git a/tests/headers/cpp-empty-layout.hpp b/bindgen-tests/tests/headers/cpp-empty-layout.hpp similarity index 100% rename from tests/headers/cpp-empty-layout.hpp rename to bindgen-tests/tests/headers/cpp-empty-layout.hpp diff --git a/tests/headers/crtp.hpp b/bindgen-tests/tests/headers/crtp.hpp similarity index 100% rename from tests/headers/crtp.hpp rename to bindgen-tests/tests/headers/crtp.hpp diff --git a/bindgen-tests/tests/headers/ctypes-prefix-path.h b/bindgen-tests/tests/headers/ctypes-prefix-path.h new file mode 100644 index 0000000000..10e06f893e --- /dev/null +++ b/bindgen-tests/tests/headers/ctypes-prefix-path.h @@ -0,0 +1,5 @@ +// bindgen-flags: --ctypes-prefix "libc::foo" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub mod foo { pub type c_int = i32; pub enum c_void {} } }" --rustified-enum ".*" +struct foo { + int a, b; + void* bar; +}; diff --git a/tests/headers/dash_language.h b/bindgen-tests/tests/headers/dash_language.h similarity index 100% rename from tests/headers/dash_language.h rename to bindgen-tests/tests/headers/dash_language.h diff --git a/tests/headers/decl_extern_int_twice.h b/bindgen-tests/tests/headers/decl_extern_int_twice.h similarity index 100% rename from tests/headers/decl_extern_int_twice.h rename to bindgen-tests/tests/headers/decl_extern_int_twice.h diff --git a/tests/headers/decl_ptr_to_array.h b/bindgen-tests/tests/headers/decl_ptr_to_array.h similarity index 100% rename from tests/headers/decl_ptr_to_array.h rename to bindgen-tests/tests/headers/decl_ptr_to_array.h diff --git a/bindgen-tests/tests/headers/default-enum-style-constified-module.h b/bindgen-tests/tests/headers/default-enum-style-constified-module.h new file mode 100644 index 0000000000..a5ba653121 --- /dev/null +++ b/bindgen-tests/tests/headers/default-enum-style-constified-module.h @@ -0,0 +1,4 @@ +// bindgen-flags: --default-enum-style moduleconsts + +typedef enum { bar, baz, blap } Foo; +void func(Foo x); diff --git a/bindgen-tests/tests/headers/default-macro-constant-type-signed.h b/bindgen-tests/tests/headers/default-macro-constant-type-signed.h new file mode 100644 index 0000000000..da3f134467 --- /dev/null +++ b/bindgen-tests/tests/headers/default-macro-constant-type-signed.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-macro-constant-type signed +// All values are i32 if they fit; otherwise i64. +#include "default-macro-constant-type.h" diff --git a/bindgen-tests/tests/headers/default-macro-constant-type-unsigned.h b/bindgen-tests/tests/headers/default-macro-constant-type-unsigned.h new file mode 100644 index 0000000000..1078e852ee --- /dev/null +++ b/bindgen-tests/tests/headers/default-macro-constant-type-unsigned.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-macro-constant-type unsigned +// Negative values are i32 or i64; others are u32 or u64. +#include "default-macro-constant-type.h" diff --git a/bindgen-tests/tests/headers/default-macro-constant-type.h b/bindgen-tests/tests/headers/default-macro-constant-type.h new file mode 100644 index 0000000000..a863362c98 --- /dev/null +++ b/bindgen-tests/tests/headers/default-macro-constant-type.h @@ -0,0 +1,52 @@ +// Test default of --default-macro-constant-type +// Negative values are i32 or i64; others are u32 or u64. + +#define N0 0 +#define N1 1ULL +#define N2 2ULL + +#define N_1 (-1LL) +#define N_2 (-2LL) + +#define MAX_U16 0xFFFFULL +#define MAX_I16 (0x8000ULL - 1) + +#define MAX_I16_Plus1 (MAX_I16 + 1) +#define MAX_U16_Plus1 (MAX_U16 + 1) + +#define MAX_I16_Minus1 (MAX_I16 - 1) +#define MAX_U16_Minus1 (MAX_U16 - 1) + +#define MIN_U16 0 +#define MIN_I16 (- (1ULL<<15)) + +#define MIN_U16_Plus1 (MIN_U16 + 1) +#define MIN_I16_Plus1 (MIN_I16 + 1) + +#define MIN_U16_Minus1 (MIN_U16 - 1) +#define MIN_I16_Minus1 (MIN_I16 - 1) + +#define MAX_U32 0xFFFFFFFFULL +#define MAX_I32 (0x80000000ULL - 1) + +#define MAX_I32_Plus1 (MAX_I32 + 1) +#define MAX_U32_Plus1 (MAX_U32 + 1) + +#define MAX_I32_Minus1 (MAX_I32 - 1) +#define MAX_U32_Minus1 (MAX_U32 - 1) + +#define MIN_U32 0 +#define MIN_I32 (- (1ULL<<31)) + +#define MIN_U32_Plus1 (MIN_U32 + 1) +#define MIN_I32_Plus1 (MIN_I32 + 1) + +#define MIN_U32_Minus1 (MIN_U32 - 1) +#define MIN_I32_Minus1 (MIN_I32 - 1) + +#define LONG12 123456789012ULL +#define LONG_12 (- 123456789012ULL) + +// Function parameter and return types are not affected. +int foo(int, signed, unsigned, char, unsigned char, signed char); +long bar(long, long long); diff --git a/tests/headers/default-template-parameter.hpp b/bindgen-tests/tests/headers/default-template-parameter.hpp similarity index 100% rename from tests/headers/default-template-parameter.hpp rename to bindgen-tests/tests/headers/default-template-parameter.hpp diff --git a/bindgen-tests/tests/headers/default_visibility_crate.h b/bindgen-tests/tests/headers/default_visibility_crate.h new file mode 100644 index 0000000000..c6f0be87c5 --- /dev/null +++ b/bindgen-tests/tests/headers/default_visibility_crate.h @@ -0,0 +1,12 @@ +// bindgen-flags: --no-layout-tests --default-visibility=crate + +struct Point { + int x; + int y; +}; + +struct Color { + char r :1; + char g :1; + char b :1; +}; diff --git a/bindgen-tests/tests/headers/default_visibility_private.h b/bindgen-tests/tests/headers/default_visibility_private.h new file mode 100644 index 0000000000..7ba75f7cb8 --- /dev/null +++ b/bindgen-tests/tests/headers/default_visibility_private.h @@ -0,0 +1,12 @@ +// bindgen-flags: --no-layout-tests --default-visibility=private + +struct Point { + int x; + int y; +}; + +struct Color { + char r :1; + char g :1; + char b :1; +}; diff --git a/bindgen-tests/tests/headers/default_visibility_private_respects_cxx_access_spec.h b/bindgen-tests/tests/headers/default_visibility_private_respects_cxx_access_spec.h new file mode 100644 index 0000000000..875484099a --- /dev/null +++ b/bindgen-tests/tests/headers/default_visibility_private_respects_cxx_access_spec.h @@ -0,0 +1,12 @@ +// bindgen-flags: --respect-cxx-access-specs --no-layout-tests --default-visibility=private + +struct Point { + int x; + int y; +}; + +struct Color { + char r :1; + char g :1; + char b :1; +}; diff --git a/bindgen-tests/tests/headers/deleted-function.hpp b/bindgen-tests/tests/headers/deleted-function.hpp new file mode 100644 index 0000000000..61848a0ae9 --- /dev/null +++ b/bindgen-tests/tests/headers/deleted-function.hpp @@ -0,0 +1,35 @@ +// bindgen-flags: --generate-inline-functions -- -std=c++11 + +class A { +public: + // Deleted function should not get a binding. + void deleted() = delete; + + // Inline functions should get bindings, whether they are defined inline + // (in the class) or out of line. + inline void inline_definition() {} + inline void out_of_line_definition(); + + // TODO: This is an edge case that we get wrong: An inline function + // without a definition in the same translation unit should still get a + // binding. We currently can't distinguish this case from a deleted member + // function because libclang doesn't provide a direct way to query for + // deleted member functions. This seems acceptable, however, as an inline + // function without a definition in the same translation unit is unlikely + // to be useful in practice. + inline void inline_without_definition(); +}; + +void A::out_of_line_definition() {} + +class B { +public: + // Deleted copy constructor should not get a binding. + B(B&) = delete; +}; + +class C { +public: + // Defaulted copy constructor should get a binding. + C(C&) = default; +}; \ No newline at end of file diff --git a/tests/headers/derive-bitfield-method-same-name.hpp b/bindgen-tests/tests/headers/derive-bitfield-method-same-name.hpp similarity index 100% rename from tests/headers/derive-bitfield-method-same-name.hpp rename to bindgen-tests/tests/headers/derive-bitfield-method-same-name.hpp diff --git a/tests/headers/derive-clone.h b/bindgen-tests/tests/headers/derive-clone.h similarity index 98% rename from tests/headers/derive-clone.h rename to bindgen-tests/tests/headers/derive-clone.h index a84d35cdd2..8dc30eacfc 100644 --- a/tests/headers/derive-clone.h +++ b/bindgen-tests/tests/headers/derive-clone.h @@ -1,4 +1,3 @@ - /// This struct should derive `Clone`. struct ShouldDeriveClone { int large[33]; diff --git a/bindgen-tests/tests/headers/derive-custom-cli.h b/bindgen-tests/tests/headers/derive-custom-cli.h new file mode 100644 index 0000000000..9b65536f94 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-custom-cli.h @@ -0,0 +1,14 @@ +// bindgen-flags: --default-enum-style rust --default-non-copy-union-style manually_drop --no-default=".*" --no-hash=".*" --no-partialeq=".*" --no-debug=".*" --no-copy=".*" --with-derive-custom="foo_[^e].*=Clone" --with-derive-custom-struct="foo.*=Default" --with-derive-custom-enum="foo.*=Copy" --with-derive-custom-union="foo.*=Copy" +struct foo_struct { + int inner; +}; +enum foo_enum { + inner = 0 +}; +union foo_union { + int fst; + float snd; +}; +struct non_matching { + int inner; +}; diff --git a/bindgen-tests/tests/headers/derive-custom.h b/bindgen-tests/tests/headers/derive-custom.h new file mode 100644 index 0000000000..8c57278cb3 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-custom.h @@ -0,0 +1,28 @@ +// bindgen-flags: --no-derive-debug --no-derive-copy --default-enum-style rust --no-layout-tests + +/**
*/ +struct my_type; + +/**
*/ +struct my_type; + +struct my_type { + int a; +}; + +/** + *
+ *
+ */ +struct my_type2; + +struct my_type2 { + unsigned a; +}; + +/** + *
+ */ +struct my_type3 { + unsigned long a; +}; diff --git a/tests/headers/derive-debug-bitfield.hpp b/bindgen-tests/tests/headers/derive-debug-bitfield-1-51.hpp similarity index 100% rename from tests/headers/derive-debug-bitfield.hpp rename to bindgen-tests/tests/headers/derive-debug-bitfield-1-51.hpp diff --git a/bindgen-tests/tests/headers/derive-debug-bitfield-core.hpp b/bindgen-tests/tests/headers/derive-debug-bitfield-core.hpp new file mode 100644 index 0000000000..5d78e74359 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-debug-bitfield-core.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;" + +class C { + bool a: 1; + bool b: 7; + int large_array[50]; +}; diff --git a/bindgen-tests/tests/headers/derive-debug-bitfield.hpp b/bindgen-tests/tests/headers/derive-debug-bitfield.hpp new file mode 100644 index 0000000000..df43e6a7c2 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-debug-bitfield.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --impl-debug + +class C { + bool a: 1; + bool b: 7; + int large_array[50]; +}; diff --git a/tests/headers/derive-debug-function-pointer.hpp b/bindgen-tests/tests/headers/derive-debug-function-pointer.hpp similarity index 100% rename from tests/headers/derive-debug-function-pointer.hpp rename to bindgen-tests/tests/headers/derive-debug-function-pointer.hpp diff --git a/tests/headers/derive-debug-generic.hpp b/bindgen-tests/tests/headers/derive-debug-generic.hpp similarity index 100% rename from tests/headers/derive-debug-generic.hpp rename to bindgen-tests/tests/headers/derive-debug-generic.hpp diff --git a/tests/headers/derive-debug-mangle-name.h b/bindgen-tests/tests/headers/derive-debug-mangle-name.h similarity index 100% rename from tests/headers/derive-debug-mangle-name.h rename to bindgen-tests/tests/headers/derive-debug-mangle-name.h diff --git a/tests/headers/derive-debug-opaque-template-instantiation.hpp b/bindgen-tests/tests/headers/derive-debug-opaque-template-instantiation.hpp similarity index 100% rename from tests/headers/derive-debug-opaque-template-instantiation.hpp rename to bindgen-tests/tests/headers/derive-debug-opaque-template-instantiation.hpp diff --git a/tests/headers/derive-debug-opaque.hpp b/bindgen-tests/tests/headers/derive-debug-opaque.hpp similarity index 100% rename from tests/headers/derive-debug-opaque.hpp rename to bindgen-tests/tests/headers/derive-debug-opaque.hpp diff --git a/bindgen-tests/tests/headers/derive-default-and-blocklist.hpp b/bindgen-tests/tests/headers/derive-default-and-blocklist.hpp new file mode 100644 index 0000000000..20d938ccf2 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-default-and-blocklist.hpp @@ -0,0 +1,14 @@ +// bindgen-flags: --blocklist-type BlocklistMe --raw-line 'pub struct BlocklistMe(u8);' + +// Note that we do not explicitly provide the `--with-derive-default` flag +// above, since it is added by the test runner implicitly. + +struct BlocklistMe {}; + +/** + * Because this type contains a blocklisted type, it should not derive + * Default. Instead, we should emit a `mem::zeroed` implementation. + */ +struct ShouldNotDeriveDefault { + BlocklistMe a; +}; diff --git a/tests/headers/derive-fn-ptr.h b/bindgen-tests/tests/headers/derive-fn-ptr.h similarity index 100% rename from tests/headers/derive-fn-ptr.h rename to bindgen-tests/tests/headers/derive-fn-ptr.h diff --git a/bindgen-tests/tests/headers/derive-hash-and-blocklist.hpp b/bindgen-tests/tests/headers/derive-hash-and-blocklist.hpp new file mode 100644 index 0000000000..51a3372fcf --- /dev/null +++ b/bindgen-tests/tests/headers/derive-hash-and-blocklist.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --with-derive-hash --blocklist-type BlocklistMe --raw-line 'pub struct BlocklistMe(u8);' + +struct BlocklistMe {}; + +/** + * Because this type contains a blocklisted type, it should not derive Hash. + */ +struct ShouldNotDeriveHash { + BlocklistMe a; +}; diff --git a/bindgen-tests/tests/headers/derive-hash-blocklisting.hpp b/bindgen-tests/tests/headers/derive-hash-blocklisting.hpp new file mode 100644 index 0000000000..4e20e3925a --- /dev/null +++ b/bindgen-tests/tests/headers/derive-hash-blocklisting.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq --allowlist-type 'Allowlisted.*' --blocklist-type Blocklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blocklisted {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell> }" +// +template +struct Blocklisted { + T t; +}; + +/// This would derive(Hash, Eq, PartialEq) if it didn't contain a blocklisted type, +/// causing us to conservatively avoid deriving hash/Eq/PartialEq for it. +struct AllowlistedOne { + Blocklisted a; +}; + +/// This can't derive(Hash/Eq) even if it didn't contain a blocklisted type. +struct AllowlistedTwo { + Blocklisted b; +}; diff --git a/tests/headers/derive-hash-struct-with-anon-struct-float.h b/bindgen-tests/tests/headers/derive-hash-struct-with-anon-struct-float.h similarity index 100% rename from tests/headers/derive-hash-struct-with-anon-struct-float.h rename to bindgen-tests/tests/headers/derive-hash-struct-with-anon-struct-float.h diff --git a/tests/headers/derive-hash-struct-with-float-array.h b/bindgen-tests/tests/headers/derive-hash-struct-with-float-array.h similarity index 100% rename from tests/headers/derive-hash-struct-with-float-array.h rename to bindgen-tests/tests/headers/derive-hash-struct-with-float-array.h diff --git a/tests/headers/derive-hash-struct-with-incomplete-array.h b/bindgen-tests/tests/headers/derive-hash-struct-with-incomplete-array.h similarity index 100% rename from tests/headers/derive-hash-struct-with-incomplete-array.h rename to bindgen-tests/tests/headers/derive-hash-struct-with-incomplete-array.h diff --git a/tests/headers/derive-hash-struct-with-pointer.h b/bindgen-tests/tests/headers/derive-hash-struct-with-pointer.h similarity index 100% rename from tests/headers/derive-hash-struct-with-pointer.h rename to bindgen-tests/tests/headers/derive-hash-struct-with-pointer.h diff --git a/tests/headers/derive-hash-template-def-float.hpp b/bindgen-tests/tests/headers/derive-hash-template-def-float.hpp similarity index 100% rename from tests/headers/derive-hash-template-def-float.hpp rename to bindgen-tests/tests/headers/derive-hash-template-def-float.hpp diff --git a/tests/headers/derive-hash-template-inst-float.hpp b/bindgen-tests/tests/headers/derive-hash-template-inst-float.hpp similarity index 100% rename from tests/headers/derive-hash-template-inst-float.hpp rename to bindgen-tests/tests/headers/derive-hash-template-inst-float.hpp diff --git a/bindgen-tests/tests/headers/derive-partialeq-and-blocklist.hpp b/bindgen-tests/tests/headers/derive-partialeq-and-blocklist.hpp new file mode 100644 index 0000000000..953d067714 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-partialeq-and-blocklist.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --with-derive-partialeq --blocklist-type BlocklistMe --raw-line 'pub struct BlocklistMe(u8);' + +struct BlocklistMe {}; + +/** + * Because this type contains a blocklisted type, it should not derive + * PartialEq. + */ +struct ShouldNotDerivePartialEq { + BlocklistMe a; +}; diff --git a/tests/headers/derive-partialeq-anonfield.h b/bindgen-tests/tests/headers/derive-partialeq-anonfield.h similarity index 100% rename from tests/headers/derive-partialeq-anonfield.h rename to bindgen-tests/tests/headers/derive-partialeq-anonfield.h diff --git a/tests/headers/derive-partialeq-base.hpp b/bindgen-tests/tests/headers/derive-partialeq-base.hpp similarity index 100% rename from tests/headers/derive-partialeq-base.hpp rename to bindgen-tests/tests/headers/derive-partialeq-base.hpp diff --git a/tests/headers/derive-partialeq-bitfield.hpp b/bindgen-tests/tests/headers/derive-partialeq-bitfield.hpp similarity index 100% rename from tests/headers/derive-partialeq-bitfield.hpp rename to bindgen-tests/tests/headers/derive-partialeq-bitfield.hpp diff --git a/tests/headers/derive-partialeq-core.h b/bindgen-tests/tests/headers/derive-partialeq-core.h similarity index 100% rename from tests/headers/derive-partialeq-core.h rename to bindgen-tests/tests/headers/derive-partialeq-core.h diff --git a/tests/headers/derive-partialeq-pointer.hpp b/bindgen-tests/tests/headers/derive-partialeq-pointer.hpp similarity index 100% rename from tests/headers/derive-partialeq-pointer.hpp rename to bindgen-tests/tests/headers/derive-partialeq-pointer.hpp diff --git a/tests/headers/derive-partialeq-union.hpp b/bindgen-tests/tests/headers/derive-partialeq-union.hpp similarity index 100% rename from tests/headers/derive-partialeq-union.hpp rename to bindgen-tests/tests/headers/derive-partialeq-union.hpp diff --git a/tests/headers/disable-namespacing.hpp b/bindgen-tests/tests/headers/disable-namespacing.hpp similarity index 100% rename from tests/headers/disable-namespacing.hpp rename to bindgen-tests/tests/headers/disable-namespacing.hpp diff --git a/bindgen-tests/tests/headers/disable-nested-struct-naming.h b/bindgen-tests/tests/headers/disable-nested-struct-naming.h new file mode 100644 index 0000000000..0e4fccb6e2 --- /dev/null +++ b/bindgen-tests/tests/headers/disable-nested-struct-naming.h @@ -0,0 +1,24 @@ +// bindgen-flags: --disable-nested-struct-naming + +struct foo { + struct bar1 { + int x1; + struct { + int x2; + struct { + int x3; + struct bar4 { + int x4; + } b4; + } b3; + } b2; + } b1; +}; + +struct { + struct { + struct baz { + int x; + } b; + } anon2; +} anon1; diff --git a/bindgen-tests/tests/headers/disable-untagged-union.hpp b/bindgen-tests/tests/headers/disable-untagged-union.hpp new file mode 100644 index 0000000000..4462318171 --- /dev/null +++ b/bindgen-tests/tests/headers/disable-untagged-union.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: --disable-untagged-union + +union Foo { + int bar; + unsigned int baz; +}; diff --git a/bindgen-tests/tests/headers/divide-by-zero-in-struct-layout.h b/bindgen-tests/tests/headers/divide-by-zero-in-struct-layout.h new file mode 100644 index 0000000000..7c500cb06d --- /dev/null +++ b/bindgen-tests/tests/headers/divide-by-zero-in-struct-layout.h @@ -0,0 +1,22 @@ +// bindgen-flags: --no-layout-tests +// +// Unfortunately, we aren't translating the third struct correctly yet. But we +// definitely shouldn't divide-by-zero when we see it... +// +// Once we fix #981 we should remove the `--no-layout-tests`. + +struct WithBitfield { + unsigned : 7; + unsigned a; +}; + +struct WithBitfieldAndAttrPacked { + unsigned : 7; + unsigned a; +} __attribute__((packed)); + +#pragma pack(1) +struct WithBitfieldAndPacked { + unsigned : 7; + unsigned a; +}; diff --git a/tests/headers/do-not-derive-copy.hpp b/bindgen-tests/tests/headers/do-not-derive-copy.hpp similarity index 100% rename from tests/headers/do-not-derive-copy.hpp rename to bindgen-tests/tests/headers/do-not-derive-copy.hpp diff --git a/tests/headers/doggo-or-null.hpp b/bindgen-tests/tests/headers/doggo-or-null.hpp similarity index 100% rename from tests/headers/doggo-or-null.hpp rename to bindgen-tests/tests/headers/doggo-or-null.hpp diff --git a/bindgen-tests/tests/headers/dupe-enum-variant-in-namespace.h b/bindgen-tests/tests/headers/dupe-enum-variant-in-namespace.h new file mode 100644 index 0000000000..2b6fb93a8e --- /dev/null +++ b/bindgen-tests/tests/headers/dupe-enum-variant-in-namespace.h @@ -0,0 +1,10 @@ +// bindgen-flags: --rustified-enum ".*" --enable-cxx-namespaces -- -x c++ -std=c++11 + +namespace foo { + enum class Bar : unsigned { + Foo = 0, + Foo1 = 0, + Foo2, + Foo3 = Foo2, + }; +} diff --git a/bindgen-tests/tests/headers/duplicated-definition-count.hpp b/bindgen-tests/tests/headers/duplicated-definition-count.hpp new file mode 100644 index 0000000000..2916762617 --- /dev/null +++ b/bindgen-tests/tests/headers/duplicated-definition-count.hpp @@ -0,0 +1,6 @@ +class BitStream { + public: + void Write(const char *inputByteArray, unsigned int numberOfBytes); + void Write(BitStream *bitStream, unsigned numberOfBits); + void Write1(); +}; diff --git a/tests/headers/duplicated-namespaces-definitions.hpp b/bindgen-tests/tests/headers/duplicated-namespaces-definitions.hpp similarity index 100% rename from tests/headers/duplicated-namespaces-definitions.hpp rename to bindgen-tests/tests/headers/duplicated-namespaces-definitions.hpp diff --git a/tests/headers/duplicated-namespaces.hpp b/bindgen-tests/tests/headers/duplicated-namespaces.hpp similarity index 100% rename from tests/headers/duplicated-namespaces.hpp rename to bindgen-tests/tests/headers/duplicated-namespaces.hpp diff --git a/tests/headers/duplicated_constants_in_ns.hpp b/bindgen-tests/tests/headers/duplicated_constants_in_ns.hpp similarity index 100% rename from tests/headers/duplicated_constants_in_ns.hpp rename to bindgen-tests/tests/headers/duplicated_constants_in_ns.hpp diff --git a/bindgen-tests/tests/headers/dynamic_loading_attributes.h b/bindgen-tests/tests/headers/dynamic_loading_attributes.h new file mode 100644 index 0000000000..e2ca62b159 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_attributes.h @@ -0,0 +1,11 @@ +// bindgen-flags: --dynamic-loading TestLib --dynamic-link-require-all --enable-function-attribute-detection +/** + * @brief A function + * + * @param x + * @param y + * @return int + */ +__attribute__((warn_unused_result)) +int foo(int x, int y); +int baz() ; diff --git a/bindgen-tests/tests/headers/dynamic_loading_required.h b/bindgen-tests/tests/headers/dynamic_loading_required.h new file mode 100644 index 0000000000..f9861e84eb --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_required.h @@ -0,0 +1,5 @@ +// bindgen-flags: --dynamic-loading TestLib --dynamic-link-require-all + +int foo(int x, int y); +int bar(void *x); +int baz(); diff --git a/bindgen-tests/tests/headers/dynamic_loading_simple.h b/bindgen-tests/tests/headers/dynamic_loading_simple.h new file mode 100644 index 0000000000..f418851beb --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_simple.h @@ -0,0 +1,5 @@ +// bindgen-flags: --dynamic-loading TestLib + +int foo(int x, int y); +int bar(void *x); +int baz(); diff --git a/bindgen-tests/tests/headers/dynamic_loading_template.hpp b/bindgen-tests/tests/headers/dynamic_loading_template.hpp new file mode 100644 index 0000000000..27f04c8e29 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_template.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --dynamic-loading TestLib + +template +T foo(T x); + +template<> +int foo(int x); + +template<> +float foo(float x); diff --git a/bindgen-tests/tests/headers/dynamic_loading_variable_required.h b/bindgen-tests/tests/headers/dynamic_loading_variable_required.h new file mode 100644 index 0000000000..8e811bb320 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_variable_required.h @@ -0,0 +1,4 @@ +// bindgen-flags: --dynamic-loading TestLib --dynamic-link-require-all + +int foo; +int *baz; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/dynamic_loading_variable_simple.h b/bindgen-tests/tests/headers/dynamic_loading_variable_simple.h new file mode 100644 index 0000000000..5ecad752ed --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_variable_simple.h @@ -0,0 +1,4 @@ +// bindgen-flags: --dynamic-loading TestLib + +int foo; +int *baz; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/dynamic_loading_variable_with_allowlist.hpp b/bindgen-tests/tests/headers/dynamic_loading_variable_with_allowlist.hpp new file mode 100644 index 0000000000..5e27303063 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_variable_with_allowlist.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --dynamic-loading TestLib --allowlist-var foo --allowlist-var bar + +int foo; +int bar; +int baz; // should not be allowed \ No newline at end of file diff --git a/bindgen-tests/tests/headers/dynamic_loading_with_allowlist.hpp b/bindgen-tests/tests/headers/dynamic_loading_with_allowlist.hpp new file mode 100644 index 0000000000..995fbdd531 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_with_allowlist.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: --dynamic-loading TestLib --allowlist-function baz --allowlist-function foo --allowlist-function bazz + +class X { + int _x; + + public: + X(int x); + + void some_function(); + void some_other_function(); +}; + +int foo(void *x); +int bar(void *x); +int baz(void *x); +int bazz(int, ...); diff --git a/bindgen-tests/tests/headers/dynamic_loading_with_blocklist.hpp b/bindgen-tests/tests/headers/dynamic_loading_with_blocklist.hpp new file mode 100644 index 0000000000..81266d1f40 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_with_blocklist.hpp @@ -0,0 +1,15 @@ +// bindgen-flags: --dynamic-loading TestLib --blocklist-function baz + +class X { + int _x; + + public: + X(int x); + + void some_function(); + void some_other_function(); +}; + +int foo(void *x); +int bar(void *x); +int baz(void *x); diff --git a/bindgen-tests/tests/headers/dynamic_loading_with_class.hpp b/bindgen-tests/tests/headers/dynamic_loading_with_class.hpp new file mode 100644 index 0000000000..632db4d065 --- /dev/null +++ b/bindgen-tests/tests/headers/dynamic_loading_with_class.hpp @@ -0,0 +1,15 @@ +// bindgen-flags: --dynamic-loading TestLib + +int foo(void *x); + +class A { + int _x; + + public: + A(int x); + + void some_function(); + void some_other_function(); +}; + +void bar(); diff --git a/tests/headers/elaborated.hpp b/bindgen-tests/tests/headers/elaborated.hpp similarity index 100% rename from tests/headers/elaborated.hpp rename to bindgen-tests/tests/headers/elaborated.hpp diff --git a/tests/headers/empty-enum.h b/bindgen-tests/tests/headers/empty-enum.h similarity index 100% rename from tests/headers/empty-enum.h rename to bindgen-tests/tests/headers/empty-enum.h diff --git a/bindgen-tests/tests/headers/empty-union.hpp b/bindgen-tests/tests/headers/empty-union.hpp new file mode 100644 index 0000000000..113a95ee30 --- /dev/null +++ b/bindgen-tests/tests/headers/empty-union.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --opaque-type ".*" + +template class a { + union {}; +}; diff --git a/tests/headers/empty_template_param_name.hpp b/bindgen-tests/tests/headers/empty_template_param_name.hpp similarity index 100% rename from tests/headers/empty_template_param_name.hpp rename to bindgen-tests/tests/headers/empty_template_param_name.hpp diff --git a/bindgen-tests/tests/headers/enum-default-bitfield.h b/bindgen-tests/tests/headers/enum-default-bitfield.h new file mode 100644 index 0000000000..5f3cb95468 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-default-bitfield.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-enum-style=bitfield --constified-enum-module=Neg + +#include "enum.h" diff --git a/bindgen-tests/tests/headers/enum-default-consts.h b/bindgen-tests/tests/headers/enum-default-consts.h new file mode 100644 index 0000000000..233d2718a4 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-default-consts.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-enum-style=consts --constified-enum-module=Neg + +#include "enum.h" diff --git a/bindgen-tests/tests/headers/enum-default-module.h b/bindgen-tests/tests/headers/enum-default-module.h new file mode 100644 index 0000000000..8c2ec1bca4 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-default-module.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-enum-style=moduleconsts --constified-enum-module=Neg + +#include "enum.h" diff --git a/bindgen-tests/tests/headers/enum-default-rust.h b/bindgen-tests/tests/headers/enum-default-rust.h new file mode 100644 index 0000000000..7fd2999fe0 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-default-rust.h @@ -0,0 +1,3 @@ +// bindgen-flags: --default-enum-style=rust --constified-enum-module=Neg + +#include "enum.h" diff --git a/tests/headers/enum-doc-bitfield.h b/bindgen-tests/tests/headers/enum-doc-bitfield.h similarity index 100% rename from tests/headers/enum-doc-bitfield.h rename to bindgen-tests/tests/headers/enum-doc-bitfield.h diff --git a/tests/headers/enum-doc-mod.h b/bindgen-tests/tests/headers/enum-doc-mod.h similarity index 100% rename from tests/headers/enum-doc-mod.h rename to bindgen-tests/tests/headers/enum-doc-mod.h diff --git a/bindgen-tests/tests/headers/enum-doc-rusty-non-exhaustive.h b/bindgen-tests/tests/headers/enum-doc-rusty-non-exhaustive.h new file mode 100644 index 0000000000..b544a0c4fc --- /dev/null +++ b/bindgen-tests/tests/headers/enum-doc-rusty-non-exhaustive.h @@ -0,0 +1,3 @@ +// bindgen-flags: --rustified-non-exhaustive-enum B + +#include "enum-doc.h" diff --git a/tests/headers/enum-doc-rusty.h b/bindgen-tests/tests/headers/enum-doc-rusty.h similarity index 100% rename from tests/headers/enum-doc-rusty.h rename to bindgen-tests/tests/headers/enum-doc-rusty.h diff --git a/bindgen-tests/tests/headers/enum-doc.h b/bindgen-tests/tests/headers/enum-doc.h new file mode 100644 index 0000000000..7a2f425cda --- /dev/null +++ b/bindgen-tests/tests/headers/enum-doc.h @@ -0,0 +1,18 @@ +/** Document enum */ +enum B { + /// Document field with three slashes + VAR_A = 0, + /** Document field with preceding star */ + VAR_B = 1, + /*! Document field with preceding exclamation */ + VAR_C = 2, + VAR_D = 3, /**< Document field with following star */ + VAR_E = 4, /*!< Document field with following exclamation */ + /** + * Document field with preceding star, with a loong long multiline + * comment. + * + * Very interesting documentation, definitely. + */ + VAR_F, +}; diff --git a/bindgen-tests/tests/headers/enum-no-debug-rust.h b/bindgen-tests/tests/headers/enum-no-debug-rust.h new file mode 100644 index 0000000000..7cb7398029 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-no-debug-rust.h @@ -0,0 +1,3 @@ +// bindgen-flags: --no-derive-debug --default-enum-style=rust --constified-enum-module=Neg + +#include "enum.h" diff --git a/bindgen-tests/tests/headers/enum-translate-type.hpp b/bindgen-tests/tests/headers/enum-translate-type.hpp new file mode 100644 index 0000000000..8d85626105 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-translate-type.hpp @@ -0,0 +1,14 @@ +// bindgen-flags: --translate-enum-integer-types -- -std=c++11 -Wno-narrowing + +enum my_enum1 { + A = 0, +}; +enum my_enum2 { + B = -1, +}; +enum my_enum3: short { + C = 0, +}; +enum my_enum4: unsigned char { + D = -1, +}; diff --git a/bindgen-tests/tests/headers/enum-typedef.h b/bindgen-tests/tests/headers/enum-typedef.h new file mode 100644 index 0000000000..f345f4de27 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-typedef.h @@ -0,0 +1,18 @@ +typedef short int16_t; + +// `cbindgen` emits this C idiom as the translation of: +// +// #[repr(i16)] +// pub enum Enum { +// Variant, +// } +enum Enum { + Variant, +}; +typedef int16_t Enum; + +// C is also fine with the typedef coming before the enum. +typedef int16_t TypedefFirst; +enum TypedefFirst { + Variant2, +}; diff --git a/bindgen-tests/tests/headers/enum-undefault.h b/bindgen-tests/tests/headers/enum-undefault.h new file mode 100644 index 0000000000..7150be0dd9 --- /dev/null +++ b/bindgen-tests/tests/headers/enum-undefault.h @@ -0,0 +1,11 @@ +// bindgen-flags: --default-enum-style=rust --constified-enum=Neg + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; diff --git a/tests/headers/enum-variant-replaces.h b/bindgen-tests/tests/headers/enum-variant-replaces.h similarity index 100% rename from tests/headers/enum-variant-replaces.h rename to bindgen-tests/tests/headers/enum-variant-replaces.h diff --git a/bindgen-tests/tests/headers/enum.h b/bindgen-tests/tests/headers/enum.h new file mode 100644 index 0000000000..0147433ee9 --- /dev/null +++ b/bindgen-tests/tests/headers/enum.h @@ -0,0 +1,31 @@ +// A few tests for enum-related issues that should be tested with all the enum +// representations. + +struct foo { + enum { + FOO_A, + FOO_B, + } member; +}; + +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; + +/**
*/ +enum NoDebug { + NoDebug1, + NoDebug2, +}; + +/**
*/ +enum Debug { + Debug1, + Debug2, +}; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/enum_alias.hpp b/bindgen-tests/tests/headers/enum_alias.hpp new file mode 100644 index 0000000000..8ddb25c36c --- /dev/null +++ b/bindgen-tests/tests/headers/enum_alias.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 + +typedef unsigned char uint8_t; + +enum Bar : uint8_t { + VAL +}; diff --git a/bindgen-tests/tests/headers/enum_and_vtable_mangling.hpp b/bindgen-tests/tests/headers/enum_and_vtable_mangling.hpp new file mode 100644 index 0000000000..659a8bd1d6 --- /dev/null +++ b/bindgen-tests/tests/headers/enum_and_vtable_mangling.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --rustified-enum ".*" + +enum { + match, + whatever_else, +}; + +class C { + int i; +public: + virtual void match(); +}; diff --git a/bindgen-tests/tests/headers/enum_dupe.h b/bindgen-tests/tests/headers/enum_dupe.h new file mode 100644 index 0000000000..b8d9689aa8 --- /dev/null +++ b/bindgen-tests/tests/headers/enum_dupe.h @@ -0,0 +1,6 @@ +// bindgen-flags: --rustified-enum ".*" + +enum Foo { + Bar = 1, + Dupe = 1 +}; diff --git a/bindgen-tests/tests/headers/enum_explicit_type.hpp b/bindgen-tests/tests/headers/enum_explicit_type.hpp new file mode 100644 index 0000000000..38e636e6c2 --- /dev/null +++ b/bindgen-tests/tests/headers/enum_explicit_type.hpp @@ -0,0 +1,42 @@ +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 + +enum Foo: unsigned char { + Bar = 0, + Qux +}; + +enum Neg: signed char { + MinusOne = -1, + One = 1, +}; + +enum Bigger: unsigned short { + Much = 255, + Larger +}; + +enum MuchLong: long { + MuchLow = -4294967296, +}; + +enum MuchLongLong: long long { + I64_MIN = 1ll << 63, +}; + +enum MuchULongLong: unsigned long long { + MuchHigh = 4294967296, +}; + +enum BoolEnumsAreFun: bool { + Value = true, +}; + +using MyType = bool; +enum BoolEnumsAreFun2: MyType { + Value2 = true, +}; + +enum : unsigned char { + AnonymousVariantOne, + AnonymousVariantTwo, +}; diff --git a/bindgen-tests/tests/headers/enum_explicit_type_constants.hpp b/bindgen-tests/tests/headers/enum_explicit_type_constants.hpp new file mode 100644 index 0000000000..e1ecf6fa8d --- /dev/null +++ b/bindgen-tests/tests/headers/enum_explicit_type_constants.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --raw-line '#![cfg(not(target_os="windows"))]' -- -std=c++11 +// +// This test is much like enum_explicit_type, but without --rustified-enum. + +#include "enum_explicit_type.hpp" diff --git a/bindgen-tests/tests/headers/enum_in_template.hpp b/bindgen-tests/tests/headers/enum_in_template.hpp new file mode 100644 index 0000000000..41c017c4bc --- /dev/null +++ b/bindgen-tests/tests/headers/enum_in_template.hpp @@ -0,0 +1,10 @@ + +template +class Foo +{ + enum Bar + { + A, + B + }; +}; diff --git a/tests/headers/enum_in_template_with_typedef.hpp b/bindgen-tests/tests/headers/enum_in_template_with_typedef.hpp similarity index 83% rename from tests/headers/enum_in_template_with_typedef.hpp rename to bindgen-tests/tests/headers/enum_in_template_with_typedef.hpp index 244d916c2e..87290ecec6 100644 --- a/tests/headers/enum_in_template_with_typedef.hpp +++ b/bindgen-tests/tests/headers/enum_in_template_with_typedef.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 namespace std { template class fbstring_core; diff --git a/bindgen-tests/tests/headers/enum_negative.h b/bindgen-tests/tests/headers/enum_negative.h new file mode 100644 index 0000000000..0fa0df9712 --- /dev/null +++ b/bindgen-tests/tests/headers/enum_negative.h @@ -0,0 +1,6 @@ +// bindgen-flags: --rustified-enum ".*" + +enum Foo { + Bar = -2, + Qux = 1, +}; diff --git a/tests/headers/enum_packed.h b/bindgen-tests/tests/headers/enum_packed.h similarity index 83% rename from tests/headers/enum_packed.h rename to bindgen-tests/tests/headers/enum_packed.h index 1c89b992ec..cc70c816d8 100644 --- a/tests/headers/enum_packed.h +++ b/bindgen-tests/tests/headers/enum_packed.h @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" enum __attribute__((packed)) Foo { Bar = 0, diff --git a/bindgen-tests/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h b/bindgen-tests/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h new file mode 100644 index 0000000000..4c342c0ec5 --- /dev/null +++ b/bindgen-tests/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h @@ -0,0 +1,5 @@ +// bindgen-flags: --raw-line "#![allow(overflowing_literals)]" + +typedef unsigned int uint32_t; + +uint32_t a = 18446744073709551611; diff --git a/bindgen-tests/tests/headers/eval-value-dependent.hpp b/bindgen-tests/tests/headers/eval-value-dependent.hpp new file mode 100644 index 0000000000..0f4dc6ab25 --- /dev/null +++ b/bindgen-tests/tests/headers/eval-value-dependent.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: -- -std=c++11 + +template class e { + using f = d; + static const auto g = alignof(f); +}; diff --git a/tests/headers/eval-variadic-template-parameter.hpp b/bindgen-tests/tests/headers/eval-variadic-template-parameter.hpp similarity index 100% rename from tests/headers/eval-variadic-template-parameter.hpp rename to bindgen-tests/tests/headers/eval-variadic-template-parameter.hpp diff --git a/bindgen-tests/tests/headers/explicit-padding.h b/bindgen-tests/tests/headers/explicit-padding.h new file mode 100644 index 0000000000..4abaafba9b --- /dev/null +++ b/bindgen-tests/tests/headers/explicit-padding.h @@ -0,0 +1,17 @@ +// bindgen-flags: --explicit-padding + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +struct pad_me { + uint8_t first; + uint32_t second; + uint16_t third; +}; + +union dont_pad_me { + uint8_t first; + uint32_t second; + uint16_t third; +}; diff --git a/bindgen-tests/tests/headers/extern-const-struct.h b/bindgen-tests/tests/headers/extern-const-struct.h new file mode 100644 index 0000000000..10006e8284 --- /dev/null +++ b/bindgen-tests/tests/headers/extern-const-struct.h @@ -0,0 +1,5 @@ +struct nsFoo { + float details[400]; +}; + +extern const struct nsFoo gDetails; diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h b/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h new file mode 100644 index 0000000000..0de6eebb36 --- /dev/null +++ b/bindgen-tests/tests/headers/extern-fn-block-attrs-many.h @@ -0,0 +1,3 @@ +// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]' --extern-fn-block-attrs '#[cfg_attr(not(windows), link(wasm_import_module = "test-module"))]' + +void test_function(); \ No newline at end of file diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h b/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h new file mode 100644 index 0000000000..2f475f1ed1 --- /dev/null +++ b/bindgen-tests/tests/headers/extern-fn-block-attrs-wasm.h @@ -0,0 +1,3 @@ +// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]' --wasm-import-module-name test-module + +void test_function(); \ No newline at end of file diff --git a/bindgen-tests/tests/headers/extern-fn-block-attrs.h b/bindgen-tests/tests/headers/extern-fn-block-attrs.h new file mode 100644 index 0000000000..26480e2ef0 --- /dev/null +++ b/bindgen-tests/tests/headers/extern-fn-block-attrs.h @@ -0,0 +1,3 @@ +// bindgen-flags: --extern-fn-block-attrs '#[allow(dead_code)]' + +void test_function(); \ No newline at end of file diff --git a/tests/headers/extern.hpp b/bindgen-tests/tests/headers/extern.hpp similarity index 100% rename from tests/headers/extern.hpp rename to bindgen-tests/tests/headers/extern.hpp diff --git a/bindgen-tests/tests/headers/extern_blocks_post_1_82.h b/bindgen-tests/tests/headers/extern_blocks_post_1_82.h new file mode 100644 index 0000000000..f7f3464e98 --- /dev/null +++ b/bindgen-tests/tests/headers/extern_blocks_post_1_82.h @@ -0,0 +1,5 @@ +// bindgen-flags: --no-layout-tests --rust-target=1.82 + +void cool_function(int i, char c); + +static int cool_static; diff --git a/bindgen-tests/tests/headers/extern_blocks_pre_1_82.h b/bindgen-tests/tests/headers/extern_blocks_pre_1_82.h new file mode 100644 index 0000000000..604625a0a3 --- /dev/null +++ b/bindgen-tests/tests/headers/extern_blocks_pre_1_82.h @@ -0,0 +1,5 @@ +// bindgen-flags: --no-layout-tests + +void cool_function(int i, char c); + +static int cool_static; diff --git a/bindgen-tests/tests/headers/field-visibility-callback.h b/bindgen-tests/tests/headers/field-visibility-callback.h new file mode 100644 index 0000000000..d2fe3ace80 --- /dev/null +++ b/bindgen-tests/tests/headers/field-visibility-callback.h @@ -0,0 +1,9 @@ +// bindgen-flags: --default-visibility private +// bindgen-parse-callbacks: field-visibility-default-private + +struct my_struct { + int a; + int private_b; + int c: 1; + int private_d: 1; +}; diff --git a/bindgen-tests/tests/headers/field-visibility.h b/bindgen-tests/tests/headers/field-visibility.h new file mode 100644 index 0000000000..adb73159c2 --- /dev/null +++ b/bindgen-tests/tests/headers/field-visibility.h @@ -0,0 +1,10 @@ +// bindgen-flags: --default-visibility private --no-doc-comments + +struct my_struct1 { + int a: 1; +}; + +/**
*/ +struct my_struct2 { + int a: 1; +}; diff --git a/bindgen-tests/tests/headers/fit-macro-constant-types-signed.h b/bindgen-tests/tests/headers/fit-macro-constant-types-signed.h new file mode 100644 index 0000000000..dba20937df --- /dev/null +++ b/bindgen-tests/tests/headers/fit-macro-constant-types-signed.h @@ -0,0 +1,2 @@ +// bindgen-flags: --default-macro-constant-type=signed --fit-macro-constant-types +#include "default-macro-constant-type.h" diff --git a/bindgen-tests/tests/headers/fit-macro-constant-types.h b/bindgen-tests/tests/headers/fit-macro-constant-types.h new file mode 100644 index 0000000000..b995bfc0d4 --- /dev/null +++ b/bindgen-tests/tests/headers/fit-macro-constant-types.h @@ -0,0 +1,4 @@ +// bindgen-flags: --fit-macro-constant-types +// Test fitting macro constants into smaller integer types +// Negative values are i8, i16, i32 or i64; others are u8, u16, u32 or u64. +#include "default-macro-constant-type.h" \ No newline at end of file diff --git a/bindgen-tests/tests/headers/flexarray.hpp b/bindgen-tests/tests/headers/flexarray.hpp new file mode 100644 index 0000000000..b698c38d19 --- /dev/null +++ b/bindgen-tests/tests/headers/flexarray.hpp @@ -0,0 +1,32 @@ +// bindgen-flags: --rust-target nightly --flexarray-dst --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(ptr_metadata, layout_for_ptr)]' + +struct flexarray { + int count; + int data[]; +}; + +struct flexarray_zero { + int count; + int data[0]; +}; + +template +struct flexarray_template { + int count; + T data[]; +}; + +struct flexarray_ref { + flexarray *things; +}; + +struct flexarray_bogus_zero_fam { + int count; + int data1[0]; + char data2[]; +}; + +struct flexarray_align { + int count; + int data[]; +} __attribute__((aligned(128))); diff --git a/tests/headers/float128.hpp b/bindgen-tests/tests/headers/float128.hpp similarity index 100% rename from tests/headers/float128.hpp rename to bindgen-tests/tests/headers/float128.hpp diff --git a/bindgen-tests/tests/headers/float16.h b/bindgen-tests/tests/headers/float16.h new file mode 100644 index 0000000000..3b1058591d --- /dev/null +++ b/bindgen-tests/tests/headers/float16.h @@ -0,0 +1,36 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq + +static __fp16 global; + +struct Test__Float16 +{ + __fp16 f; +}; + +struct Test__Float16Ref +{ + __fp16 *f; +}; + +/* +// This options are currently supported only on specific targets (eg. x86 with sse2) +_Float16 returns_f16(); + +void gets_f16(_Float16 arg); + +struct Test__Float16_Complex +{ + _Float16 _Complex mMember; +}; + +struct Test__Float16_ComplexPtr +{ + _Float16 _Complex *mMember; +}; + +_Float16 _Complex globalValueHalf; + +_Float16 _Complex returns_f16_complex(); + +void gets_f16_complex(_Float16 _Complex arg); +*/ \ No newline at end of file diff --git a/tests/headers/forward-declaration-autoptr.hpp b/bindgen-tests/tests/headers/forward-declaration-autoptr.hpp similarity index 100% rename from tests/headers/forward-declaration-autoptr.hpp rename to bindgen-tests/tests/headers/forward-declaration-autoptr.hpp diff --git a/bindgen-tests/tests/headers/forward-enum-decl.hpp b/bindgen-tests/tests/headers/forward-enum-decl.hpp new file mode 100644 index 0000000000..81a0eee731 --- /dev/null +++ b/bindgen-tests/tests/headers/forward-enum-decl.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 + +enum class CSSPseudoClassType : int; + +enum class CSSPseudoClassType : int { + empty, + link, +}; diff --git a/tests/headers/forward-inherit-struct-with-fields.hpp b/bindgen-tests/tests/headers/forward-inherit-struct-with-fields.hpp similarity index 100% rename from tests/headers/forward-inherit-struct-with-fields.hpp rename to bindgen-tests/tests/headers/forward-inherit-struct-with-fields.hpp diff --git a/tests/headers/forward-inherit-struct.hpp b/bindgen-tests/tests/headers/forward-inherit-struct.hpp similarity index 100% rename from tests/headers/forward-inherit-struct.hpp rename to bindgen-tests/tests/headers/forward-inherit-struct.hpp diff --git a/tests/headers/forward_declared_complex_types.hpp b/bindgen-tests/tests/headers/forward_declared_complex_types.hpp similarity index 100% rename from tests/headers/forward_declared_complex_types.hpp rename to bindgen-tests/tests/headers/forward_declared_complex_types.hpp diff --git a/bindgen-tests/tests/headers/forward_declared_opaque.h b/bindgen-tests/tests/headers/forward_declared_opaque.h new file mode 100644 index 0000000000..69a12cc7e2 --- /dev/null +++ b/bindgen-tests/tests/headers/forward_declared_opaque.h @@ -0,0 +1,4 @@ +// bindgen-flags: --opaque-type ".*" + +union a; +struct b; diff --git a/tests/headers/forward_declared_struct.h b/bindgen-tests/tests/headers/forward_declared_struct.h similarity index 100% rename from tests/headers/forward_declared_struct.h rename to bindgen-tests/tests/headers/forward_declared_struct.h diff --git a/tests/headers/func_proto.h b/bindgen-tests/tests/headers/func_proto.h similarity index 100% rename from tests/headers/func_proto.h rename to bindgen-tests/tests/headers/func_proto.h diff --git a/tests/headers/func_ptr.h b/bindgen-tests/tests/headers/func_ptr.h similarity index 100% rename from tests/headers/func_ptr.h rename to bindgen-tests/tests/headers/func_ptr.h diff --git a/tests/headers/func_ptr_in_struct.h b/bindgen-tests/tests/headers/func_ptr_in_struct.h similarity index 78% rename from tests/headers/func_ptr_in_struct.h rename to bindgen-tests/tests/headers/func_ptr_in_struct.h index dd608549ae..ef075df76c 100644 --- a/tests/headers/func_ptr_in_struct.h +++ b/bindgen-tests/tests/headers/func_ptr_in_struct.h @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" // enum baz; diff --git a/bindgen-tests/tests/headers/func_ptr_return_type.h b/bindgen-tests/tests/headers/func_ptr_return_type.h new file mode 100644 index 0000000000..d529edc770 --- /dev/null +++ b/bindgen-tests/tests/headers/func_ptr_return_type.h @@ -0,0 +1 @@ +int (*func(void))(int, int); diff --git a/bindgen-tests/tests/headers/func_return_must_use.h b/bindgen-tests/tests/headers/func_return_must_use.h new file mode 100644 index 0000000000..f05bd2de40 --- /dev/null +++ b/bindgen-tests/tests/headers/func_return_must_use.h @@ -0,0 +1,36 @@ +// bindgen-flags: --must-use-type 'MustUse.*' + +typedef int MustUseInt; + +MustUseInt return_int(); + +struct MustUseStruct; + +struct MustUseStruct return_struct(); + +/** + *
+ */ +typedef int AnnotatedInt; + +AnnotatedInt return_annotated_int(); + +int return_plain_int(); + +/** + *
+ */ +struct AnnotatedStruct {}; + +struct AnnotatedStruct return_annotated_struct(); + +struct PlainStruct {}; + +/** + *
+ */ +typedef struct PlainStruct TypedefPlainStruct; + +struct PlainStruct return_plain_struct(); + +TypedefPlainStruct return_typedef_struct(); diff --git a/tests/headers/func_with_array_arg.h b/bindgen-tests/tests/headers/func_with_array_arg.h similarity index 100% rename from tests/headers/func_with_array_arg.h rename to bindgen-tests/tests/headers/func_with_array_arg.h diff --git a/bindgen-tests/tests/headers/func_with_func_ptr_arg.h b/bindgen-tests/tests/headers/func_with_func_ptr_arg.h new file mode 100644 index 0000000000..e9abcae688 --- /dev/null +++ b/bindgen-tests/tests/headers/func_with_func_ptr_arg.h @@ -0,0 +1,3 @@ +void foo(void (*bar)()); + +void bar(void (*one)(int a, int b), void (*two)(int c, int d)); diff --git a/bindgen-tests/tests/headers/function-typedef-stdcall.h b/bindgen-tests/tests/headers/function-typedef-stdcall.h new file mode 100644 index 0000000000..05d1e78a26 --- /dev/null +++ b/bindgen-tests/tests/headers/function-typedef-stdcall.h @@ -0,0 +1,12 @@ +typedef + void __stdcall + EVT_VIGEM_X360_NOTIFICATION( + void* Client, + void* Target, + unsigned char LargeMotor, + unsigned char SmallMotor, + unsigned char LedNumber, + void* UserData + ); + +typedef EVT_VIGEM_X360_NOTIFICATION *PFN_VIGEM_X360_NOTIFICATION; diff --git a/tests/headers/gen-constructors-neg.hpp b/bindgen-tests/tests/headers/gen-constructors-neg.hpp similarity index 100% rename from tests/headers/gen-constructors-neg.hpp rename to bindgen-tests/tests/headers/gen-constructors-neg.hpp diff --git a/tests/headers/gen-constructors.hpp b/bindgen-tests/tests/headers/gen-constructors.hpp similarity index 100% rename from tests/headers/gen-constructors.hpp rename to bindgen-tests/tests/headers/gen-constructors.hpp diff --git a/tests/headers/gen-destructors-neg.hpp b/bindgen-tests/tests/headers/gen-destructors-neg.hpp similarity index 100% rename from tests/headers/gen-destructors-neg.hpp rename to bindgen-tests/tests/headers/gen-destructors-neg.hpp diff --git a/tests/headers/gen-destructors.hpp b/bindgen-tests/tests/headers/gen-destructors.hpp similarity index 100% rename from tests/headers/gen-destructors.hpp rename to bindgen-tests/tests/headers/gen-destructors.hpp diff --git a/tests/headers/generate-inline.hpp b/bindgen-tests/tests/headers/generate-inline.hpp similarity index 100% rename from tests/headers/generate-inline.hpp rename to bindgen-tests/tests/headers/generate-inline.hpp diff --git a/bindgen-tests/tests/headers/i128.h b/bindgen-tests/tests/headers/i128.h new file mode 100644 index 0000000000..1880f11305 --- /dev/null +++ b/bindgen-tests/tests/headers/i128.h @@ -0,0 +1,4 @@ +struct foo { + __int128 my_signed; + unsigned __int128 my_unsigned; +}; diff --git a/tests/headers/in_class_typedef.hpp b/bindgen-tests/tests/headers/in_class_typedef.hpp similarity index 100% rename from tests/headers/in_class_typedef.hpp rename to bindgen-tests/tests/headers/in_class_typedef.hpp diff --git a/bindgen-tests/tests/headers/incomplete-array-padding.h b/bindgen-tests/tests/headers/incomplete-array-padding.h new file mode 100644 index 0000000000..3fcc4c1a09 --- /dev/null +++ b/bindgen-tests/tests/headers/incomplete-array-padding.h @@ -0,0 +1,4 @@ +struct foo { + char a : 1; + void *b[]; +}; diff --git a/bindgen-tests/tests/headers/infinite-macro.hpp b/bindgen-tests/tests/headers/infinite-macro.hpp new file mode 100644 index 0000000000..32c8b61911 --- /dev/null +++ b/bindgen-tests/tests/headers/infinite-macro.hpp @@ -0,0 +1,7 @@ +#define INFINITY (1.0f/0.0f) +#define NEG_INFINITY (-1.0f/0.0f) +#define NAN (0.0f/0.0f) + +static const float F32_INFINITY = 1.0f / 0.0f; +static const float F32_NEG_INFINITY = -1.0f / 0.0f; +static const float F32_NAN = 0.0f / 0.0f; diff --git a/tests/headers/inherit-from-template-instantiation-with-vtable.hpp b/bindgen-tests/tests/headers/inherit-from-template-instantiation-with-vtable.hpp similarity index 100% rename from tests/headers/inherit-from-template-instantiation-with-vtable.hpp rename to bindgen-tests/tests/headers/inherit-from-template-instantiation-with-vtable.hpp diff --git a/tests/headers/inherit-namespaced.hpp b/bindgen-tests/tests/headers/inherit-namespaced.hpp similarity index 100% rename from tests/headers/inherit-namespaced.hpp rename to bindgen-tests/tests/headers/inherit-namespaced.hpp diff --git a/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp b/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp new file mode 100644 index 0000000000..725992c7cd --- /dev/null +++ b/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp @@ -0,0 +1,15 @@ +class A { + virtual void Foo(); + + int member; +}; + +class B { + virtual void Bar(); + + void* member2; +}; + +class C : public A, public B { + float member3; +}; diff --git a/tests/headers/inherit_named.hpp b/bindgen-tests/tests/headers/inherit_named.hpp similarity index 100% rename from tests/headers/inherit_named.hpp rename to bindgen-tests/tests/headers/inherit_named.hpp diff --git a/tests/headers/inherit_typedef.hpp b/bindgen-tests/tests/headers/inherit_typedef.hpp similarity index 100% rename from tests/headers/inherit_typedef.hpp rename to bindgen-tests/tests/headers/inherit_typedef.hpp diff --git a/tests/headers/inline-function.h b/bindgen-tests/tests/headers/inline-function.h similarity index 100% rename from tests/headers/inline-function.h rename to bindgen-tests/tests/headers/inline-function.h diff --git a/tests/headers/inline_namespace.hpp b/bindgen-tests/tests/headers/inline_namespace.hpp similarity index 100% rename from tests/headers/inline_namespace.hpp rename to bindgen-tests/tests/headers/inline_namespace.hpp diff --git a/bindgen-tests/tests/headers/inline_namespace_allowlist.hpp b/bindgen-tests/tests/headers/inline_namespace_allowlist.hpp new file mode 100644 index 0000000000..90e46dfb84 --- /dev/null +++ b/bindgen-tests/tests/headers/inline_namespace_allowlist.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type=std::string -- -std=c++11 + +namespace std { + inline namespace bar { + using string = const char*; + }; +}; diff --git a/tests/headers/inline_namespace_conservative.hpp b/bindgen-tests/tests/headers/inline_namespace_conservative.hpp similarity index 100% rename from tests/headers/inline_namespace_conservative.hpp rename to bindgen-tests/tests/headers/inline_namespace_conservative.hpp diff --git a/bindgen-tests/tests/headers/inline_namespace_macro.hpp b/bindgen-tests/tests/headers/inline_namespace_macro.hpp new file mode 100644 index 0000000000..c7cf5caf98 --- /dev/null +++ b/bindgen-tests/tests/headers/inline_namespace_macro.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --enable-cxx-namespaces -- -std=c++11 + +#include "namespace/nsdefine.h" + +BEGIN_NAMESPACE + +class duration {}; + +END_NAMESPACE diff --git a/bindgen-tests/tests/headers/inline_namespace_nested.hpp b/bindgen-tests/tests/headers/inline_namespace_nested.hpp new file mode 100644 index 0000000000..5c542e195c --- /dev/null +++ b/bindgen-tests/tests/headers/inline_namespace_nested.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --enable-cxx-namespaces -- -std=c++2a + +namespace ranges::inline foo::bar { + static int bar = 0; +} diff --git a/tests/headers/inline_namespace_no_ns_enabled.hpp b/bindgen-tests/tests/headers/inline_namespace_no_ns_enabled.hpp similarity index 100% rename from tests/headers/inline_namespace_no_ns_enabled.hpp rename to bindgen-tests/tests/headers/inline_namespace_no_ns_enabled.hpp diff --git a/bindgen-tests/tests/headers/inner-typedef-gh422.hpp b/bindgen-tests/tests/headers/inner-typedef-gh422.hpp new file mode 100644 index 0000000000..301630a5e0 --- /dev/null +++ b/bindgen-tests/tests/headers/inner-typedef-gh422.hpp @@ -0,0 +1,11 @@ +template +class Foo { +public: + class InnerType { + T t; + }; +}; + +typedef Foo::InnerType Bar; + +Bar func(); \ No newline at end of file diff --git a/tests/headers/inner_const.hpp b/bindgen-tests/tests/headers/inner_const.hpp similarity index 100% rename from tests/headers/inner_const.hpp rename to bindgen-tests/tests/headers/inner_const.hpp diff --git a/tests/headers/inner_template_self.hpp b/bindgen-tests/tests/headers/inner_template_self.hpp similarity index 100% rename from tests/headers/inner_template_self.hpp rename to bindgen-tests/tests/headers/inner_template_self.hpp diff --git a/tests/headers/int128_t.h b/bindgen-tests/tests/headers/int128_t.h similarity index 100% rename from tests/headers/int128_t.h rename to bindgen-tests/tests/headers/int128_t.h diff --git a/tests/headers/issue-1025-unknown-enum-repr.hpp b/bindgen-tests/tests/headers/issue-1025-unknown-enum-repr.hpp similarity index 100% rename from tests/headers/issue-1025-unknown-enum-repr.hpp rename to bindgen-tests/tests/headers/issue-1025-unknown-enum-repr.hpp diff --git a/tests/headers/issue-1034.h b/bindgen-tests/tests/headers/issue-1034.h similarity index 100% rename from tests/headers/issue-1034.h rename to bindgen-tests/tests/headers/issue-1034.h diff --git a/tests/headers/issue-1040.h b/bindgen-tests/tests/headers/issue-1040.h similarity index 100% rename from tests/headers/issue-1040.h rename to bindgen-tests/tests/headers/issue-1040.h diff --git a/tests/headers/issue-1076-unnamed-bitfield-alignment.h b/bindgen-tests/tests/headers/issue-1076-unnamed-bitfield-alignment.h similarity index 100% rename from tests/headers/issue-1076-unnamed-bitfield-alignment.h rename to bindgen-tests/tests/headers/issue-1076-unnamed-bitfield-alignment.h diff --git a/tests/headers/issue-1113-template-references.hpp b/bindgen-tests/tests/headers/issue-1113-template-references.hpp similarity index 100% rename from tests/headers/issue-1113-template-references.hpp rename to bindgen-tests/tests/headers/issue-1113-template-references.hpp diff --git a/tests/headers/issue-1118-using-forward-decl.hpp b/bindgen-tests/tests/headers/issue-1118-using-forward-decl.hpp similarity index 100% rename from tests/headers/issue-1118-using-forward-decl.hpp rename to bindgen-tests/tests/headers/issue-1118-using-forward-decl.hpp diff --git a/tests/headers/issue-1197-pure-virtual-stuff.hpp b/bindgen-tests/tests/headers/issue-1197-pure-virtual-stuff.hpp similarity index 100% rename from tests/headers/issue-1197-pure-virtual-stuff.hpp rename to bindgen-tests/tests/headers/issue-1197-pure-virtual-stuff.hpp diff --git a/tests/headers/issue-1198-alias-rust-bitfield-enum.h b/bindgen-tests/tests/headers/issue-1198-alias-rust-bitfield-enum.h similarity index 100% rename from tests/headers/issue-1198-alias-rust-bitfield-enum.h rename to bindgen-tests/tests/headers/issue-1198-alias-rust-bitfield-enum.h diff --git a/tests/headers/issue-1198-alias-rust-const-mod-bitfield-enum.h b/bindgen-tests/tests/headers/issue-1198-alias-rust-const-mod-bitfield-enum.h similarity index 100% rename from tests/headers/issue-1198-alias-rust-const-mod-bitfield-enum.h rename to bindgen-tests/tests/headers/issue-1198-alias-rust-const-mod-bitfield-enum.h diff --git a/tests/headers/issue-1198-alias-rust-const-mod-enum.h b/bindgen-tests/tests/headers/issue-1198-alias-rust-const-mod-enum.h similarity index 100% rename from tests/headers/issue-1198-alias-rust-const-mod-enum.h rename to bindgen-tests/tests/headers/issue-1198-alias-rust-const-mod-enum.h diff --git a/tests/headers/issue-1198-alias-rust-enum.h b/bindgen-tests/tests/headers/issue-1198-alias-rust-enum.h similarity index 100% rename from tests/headers/issue-1198-alias-rust-enum.h rename to bindgen-tests/tests/headers/issue-1198-alias-rust-enum.h diff --git a/tests/headers/issue-1216-variadic-member.h b/bindgen-tests/tests/headers/issue-1216-variadic-member.h similarity index 100% rename from tests/headers/issue-1216-variadic-member.h rename to bindgen-tests/tests/headers/issue-1216-variadic-member.h diff --git a/tests/headers/issue-1238-fwd-no-copy.h b/bindgen-tests/tests/headers/issue-1238-fwd-no-copy.h similarity index 100% rename from tests/headers/issue-1238-fwd-no-copy.h rename to bindgen-tests/tests/headers/issue-1238-fwd-no-copy.h diff --git a/tests/headers/issue-1281.h b/bindgen-tests/tests/headers/issue-1281.h similarity index 100% rename from tests/headers/issue-1281.h rename to bindgen-tests/tests/headers/issue-1281.h diff --git a/bindgen-tests/tests/headers/issue-1285.h b/bindgen-tests/tests/headers/issue-1285.h new file mode 100644 index 0000000000..a2817d84b4 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1285.h @@ -0,0 +1,8 @@ +// bindgen-flags: --with-derive-hash --no-recursive-allowlist --allowlist-type "foo" + +struct foo { + union { + unsigned int a; + unsigned short b; + } bar; +}; \ No newline at end of file diff --git a/tests/headers/issue-1291.hpp b/bindgen-tests/tests/headers/issue-1291.hpp similarity index 89% rename from tests/headers/issue-1291.hpp rename to bindgen-tests/tests/headers/issue-1291.hpp index 4ec524f12f..cb4aeb91f8 100644 --- a/tests/headers/issue-1291.hpp +++ b/bindgen-tests/tests/headers/issue-1291.hpp @@ -1,4 +1,3 @@ -// bindgen-flags: --rust-target 1.25 // bindgen-unstable struct __attribute__((aligned(16))) RTCRay diff --git a/bindgen-tests/tests/headers/issue-1350-attribute-overloadable.h b/bindgen-tests/tests/headers/issue-1350-attribute-overloadable.h new file mode 100644 index 0000000000..4b0ec2a6aa --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1350-attribute-overloadable.h @@ -0,0 +1,2 @@ +void my_function(int a) __attribute__((overloadable)); +void my_function(const char *a) __attribute__((overloadable)); diff --git a/bindgen-tests/tests/headers/issue-1375-prefixed-functions.h b/bindgen-tests/tests/headers/issue-1375-prefixed-functions.h new file mode 100644 index 0000000000..cc37c8ad80 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1375-prefixed-functions.h @@ -0,0 +1,8 @@ +// bindgen-parse-callbacks: remove-function-prefix-my_custom_prefix_ + +extern const int my_custom_prefix_var_const_name; + +extern int my_custom_prefix_var_mut_name; + +void my_custom_prefix_function_name(const int x); + diff --git a/bindgen-tests/tests/headers/issue-1382-rust-primitive-types.h b/bindgen-tests/tests/headers/issue-1382-rust-primitive-types.h new file mode 100644 index 0000000000..4cf346e6c9 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1382-rust-primitive-types.h @@ -0,0 +1,34 @@ +typedef int int8_t; +typedef int uint8_t; +typedef int int16_t; +typedef int uint16_t; +typedef int int32_t; +typedef int uint32_t; +typedef int int64_t; +typedef int uint64_t; + +typedef int8_t i8; +typedef uint8_t u8; +typedef int16_t i16; +typedef uint16_t u16; +typedef int32_t i32; +typedef uint32_t u32; +typedef int64_t i64; +typedef uint64_t u64; + +struct Foo { + int i8; + int u8; + int i16; + int u16; + int i32; + int u32; + int i64; + int u64; + int i128; + int u128; + int isize; + int usize; + int f32; + int f64; +}; diff --git a/bindgen-tests/tests/headers/issue-1435.hpp b/bindgen-tests/tests/headers/issue-1435.hpp new file mode 100644 index 0000000000..fbf3c5070b --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1435.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --enable-cxx-namespaces + +namespace ns { +enum class AB { A, B }; +} +using AB = ns::AB; +static const AB kA = AB::A; diff --git a/bindgen-tests/tests/headers/issue-1443.hpp b/bindgen-tests/tests/headers/issue-1443.hpp new file mode 100644 index 0000000000..9b637ba708 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1443.hpp @@ -0,0 +1,21 @@ +struct Foo; + +struct Bar { + const Foo& f; + unsigned m; +}; + +struct Baz { + Foo& f; + unsigned m; +}; + +struct Tar { + const Foo&& f; + unsigned m; +}; + +struct Taz { + Foo&& f; + unsigned m; +}; diff --git a/bindgen-tests/tests/headers/issue-1454.h b/bindgen-tests/tests/headers/issue-1454.h new file mode 100644 index 0000000000..96645dac9d --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1454.h @@ -0,0 +1,10 @@ +// bindgen-flags: --no-recursive-allowlist --allowlist-type "local_type" --with-derive-hash --no-derive-copy --no-derive-default --raw-line "#[repr(C)] #[derive(Debug)] pub struct extern_type;" +// bindgen-parse-callbacks: blocklisted-type-implements-trait + +struct extern_type {}; + +typedef struct +{ + struct extern_type inner; +} +local_type; diff --git a/bindgen-tests/tests/headers/issue-1464.hpp b/bindgen-tests/tests/headers/issue-1464.hpp new file mode 100644 index 0000000000..d34d0fe3e5 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1464.hpp @@ -0,0 +1,7 @@ + +// Should not crash. +template class Bar { +public: + Bar(); + ~Bar(); +}; diff --git a/bindgen-tests/tests/headers/issue-1488-enum-new-type.h b/bindgen-tests/tests/headers/issue-1488-enum-new-type.h new file mode 100644 index 0000000000..6855283ffb --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1488-enum-new-type.h @@ -0,0 +1,29 @@ +// bindgen-flags: --default-alias-style=new_type --constified-enum "Foo" --constified-enum-module "Bar" --rustified-enum "Qux" --new-type-alias-deref "BazAlias" + +enum Foo { + A, + B +}; + +typedef enum Foo FooAlias; + +enum Bar { + C, + D +}; + +typedef enum Bar BarAlias; + +enum Qux { + E, + F +}; + +typedef enum Qux QuxAlias; + +enum Baz { + G, + H +}; + +typedef enum Baz BazAlias; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/issue-1488-options.h b/bindgen-tests/tests/headers/issue-1488-options.h new file mode 100644 index 0000000000..fba1c93bac --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1488-options.h @@ -0,0 +1,5 @@ +// bindgen-flags: --new-type-alias "SomePtr" --new-type-alias-deref "AnotherPtr" + +typedef int OSStatus; +typedef void* SomePtr; +typedef void* AnotherPtr; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/issue-1488-template-alias-new-type.hpp b/bindgen-tests/tests/headers/issue-1488-template-alias-new-type.hpp new file mode 100644 index 0000000000..4374da3db2 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1488-template-alias-new-type.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --default-alias-style=new_type -- -std=c++14 + +template +using Wrapped = T; diff --git a/bindgen-tests/tests/headers/issue-1498.h b/bindgen-tests/tests/headers/issue-1498.h new file mode 100644 index 0000000000..aceabbd2b4 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1498.h @@ -0,0 +1,17 @@ +typedef unsigned long uint64_t; +typedef uint64_t size_t; +typedef unsigned uint32_t; +typedef int int32_t; + +struct rte_memseg { + uint64_t phys_addr; /**< Start physical address. */ + union { + void *addr; /**< Start virtual address. */ + uint64_t addr_64; /**< Makes sure addr is always 64 bits */ + }; + size_t len; /**< Length of the segment. */ + uint64_t hugepage_sz; /**< The pagesize of underlying memory */ + int32_t socket_id; /**< NUMA socket ID. */ + uint32_t nchannel; /**< Number of channels. */ + uint32_t nrank; /**< Number of ranks. */ +} __attribute__((__packed__)); diff --git a/bindgen-tests/tests/headers/issue-1514.hpp b/bindgen-tests/tests/headers/issue-1514.hpp new file mode 100644 index 0000000000..2a39889885 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1514.hpp @@ -0,0 +1,9 @@ +template +struct Thing { + struct Inner { + T *ptr; + }; + + struct AnotherInner : Inner { + }; +}; diff --git a/bindgen-tests/tests/headers/issue-1554.h b/bindgen-tests/tests/headers/issue-1554.h new file mode 100644 index 0000000000..13452923f8 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1554.h @@ -0,0 +1,6 @@ +// bindgen-flags: --default-enum-style rust_non_exhaustive --rust-target nightly --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(non_exhaustive)]' + +enum Planet { + earth, + mars +}; diff --git a/bindgen-tests/tests/headers/issue-1599-opaque-typedef-to-enum.h b/bindgen-tests/tests/headers/issue-1599-opaque-typedef-to-enum.h new file mode 100644 index 0000000000..85e845b85c --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1599-opaque-typedef-to-enum.h @@ -0,0 +1,3 @@ +// bindgen-flags: --opaque-type d + +typedef enum a { b, c } d; diff --git a/bindgen-tests/tests/headers/issue-1676-macro-namespace-prefix.hpp b/bindgen-tests/tests/headers/issue-1676-macro-namespace-prefix.hpp new file mode 100644 index 0000000000..297927b621 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1676-macro-namespace-prefix.hpp @@ -0,0 +1,2 @@ +#define nssv_inline_ns inline +nssv_inline_ns namespace literals {} diff --git a/bindgen-tests/tests/headers/issue-1947.h b/bindgen-tests/tests/headers/issue-1947.h new file mode 100644 index 0000000000..e2e9b3e19a --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1947.h @@ -0,0 +1,9 @@ +typedef unsigned char U8; +typedef unsigned short U16; + +typedef struct { + U16 MADZ : 10, MAI0 : 2, MAI1 : 2, MAI2 : 2; + U8 MADK, MABR; + U16 MATH : 10, MATE : 4, MATW : 2; + U8 MASW : 4, MABW : 3, MAXN : 1, _rB_; +} V56AMDY; diff --git a/tests/headers/struct_with_large_array.hpp b/bindgen-tests/tests/headers/issue-1977-larger-arrays.hpp similarity index 100% rename from tests/headers/struct_with_large_array.hpp rename to bindgen-tests/tests/headers/issue-1977-larger-arrays.hpp diff --git a/bindgen-tests/tests/headers/issue-1995.h b/bindgen-tests/tests/headers/issue-1995.h new file mode 100644 index 0000000000..619f673540 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-1995.h @@ -0,0 +1,12 @@ +/// This is a constant that has a docstring +/// +/// And expected to be found in generated bindings code too. +const int FOO = 1; + +/// This is a constant that has a docstring +/// +/// And expected to be found in generated bindings code too. +struct Bar +{ + int baz; +}; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/issue-2019.hpp b/bindgen-tests/tests/headers/issue-2019.hpp new file mode 100644 index 0000000000..2e9a3ffd72 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2019.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --disable-nested-struct-naming + +struct A { + static A make(); + int a; +}; +struct B { + static B make(); + int b; +}; diff --git a/bindgen-tests/tests/headers/issue-2239-template-dependent-bit-width.hpp b/bindgen-tests/tests/headers/issue-2239-template-dependent-bit-width.hpp new file mode 100644 index 0000000000..4e6feb3f1e --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2239-template-dependent-bit-width.hpp @@ -0,0 +1,10 @@ +template class b { + typedef a td; + using ta = a; + struct foo { + a foo : sizeof(a); + a : sizeof(a); + td : sizeof(td); + ta : sizeof(ta); + }; +}; diff --git a/bindgen-tests/tests/headers/issue-2556.h b/bindgen-tests/tests/headers/issue-2556.h new file mode 100644 index 0000000000..bbb1b874ec --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2556.h @@ -0,0 +1,4 @@ +// bindgen-flags: --enable-cxx-namespaces -- -x c++ -Itests/headers -include tests/headers/issue-2556/nsStyleStruct.h -include tests/headers/issue-2556/LayoutConstants.h + +#include "issue-2556/nsSize.h" +#include "issue-2556/nsStyleStruct.h" diff --git a/bindgen-tests/tests/headers/issue-2556/LayoutConstants.h b/bindgen-tests/tests/headers/issue-2556/LayoutConstants.h new file mode 100644 index 0000000000..2ed1c864b2 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2556/LayoutConstants.h @@ -0,0 +1,7 @@ +#include "nsSize.h" + +namespace foo { + +static constexpr nsSize kFallbackIntrinsicSize(0, 0); + +} diff --git a/bindgen-tests/tests/headers/issue-2556/nsSize.h b/bindgen-tests/tests/headers/issue-2556/nsSize.h new file mode 100644 index 0000000000..8fe8b95023 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2556/nsSize.h @@ -0,0 +1,6 @@ +#pragma once + +struct nsSize { + int width, height; + constexpr nsSize(int aWidth, int aHeight) : width(aWidth), height(aHeight) {} +}; diff --git a/bindgen-tests/tests/headers/issue-2556/nsStyleStruct.h b/bindgen-tests/tests/headers/issue-2556/nsStyleStruct.h new file mode 100644 index 0000000000..4c6eedfb9a --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2556/nsStyleStruct.h @@ -0,0 +1,3 @@ +#pragma once + +#include "nsSize.h" diff --git a/bindgen-tests/tests/headers/issue-2566-cstr.h b/bindgen-tests/tests/headers/issue-2566-cstr.h new file mode 100644 index 0000000000..674b894024 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2566-cstr.h @@ -0,0 +1,4 @@ +// bindgen-flags: --generate-cstr + +/// We should _not_ generate a cstr for this because cstr shouldn't have interior nulls. +#define FOO "a\0b" diff --git a/bindgen-tests/tests/headers/issue-2566.h b/bindgen-tests/tests/headers/issue-2566.h new file mode 100644 index 0000000000..6e15ec1979 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2566.h @@ -0,0 +1 @@ +#define FOO "a\0b" diff --git a/bindgen-tests/tests/headers/issue-2618.h b/bindgen-tests/tests/headers/issue-2618.h new file mode 100644 index 0000000000..841ff61d77 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2618.h @@ -0,0 +1,18 @@ +// bindgen-flags: --allowlist-var "val[0-9]+" + +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; + +static const uint32_t val1 = 0x7fffffff; +static const uint32_t val2 = 0x80000000; +static const uint32_t val3 = 0xffffffff; +static const uint64_t val4 = 0x7fffffffffffffff; +static const uint64_t val5 = 0x8000000000000000; +static const uint64_t val6 = 0xffffffffffffffff; + +static const uint32_t val7 = (0x7fffffff); +static const uint32_t val8 = (0x80000000); +static const uint32_t val9 = (0xffffffff); +static const uint64_t val10 = (0x7fffffffffffffff); +static const uint64_t val11 = (0x8000000000000000); +static const uint64_t val12 = (0xffffffffffffffff); diff --git a/bindgen-tests/tests/headers/issue-2695.h b/bindgen-tests/tests/headers/issue-2695.h new file mode 100644 index 0000000000..4fbcc39bf8 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2695.h @@ -0,0 +1,10 @@ +// bindgen-flags: --explicit-padding + +#pragma pack(2) + +struct Test { + unsigned long x; + char a; + char b; + char c; +}; diff --git a/bindgen-tests/tests/headers/issue-2966.h b/bindgen-tests/tests/headers/issue-2966.h new file mode 100644 index 0000000000..3f00dec65d --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2966.h @@ -0,0 +1,6 @@ +// bindgen-flags: --default-alias-style=new_type +// bindgen-parse-callbacks: type-visibility + +typedef const char * pub_var1; +typedef const char * pubcrate_var2; +typedef const char * private_var3; diff --git a/bindgen-tests/tests/headers/issue-3027.hpp b/bindgen-tests/tests/headers/issue-3027.hpp new file mode 100644 index 0000000000..d9b87ee6e2 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-3027.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: --enable-cxx-namespaces + +namespace regression { + template class A { char c[N]; }; + class C { A<3> a; }; +} diff --git a/tests/headers/issue-358.hpp b/bindgen-tests/tests/headers/issue-358.hpp similarity index 100% rename from tests/headers/issue-358.hpp rename to bindgen-tests/tests/headers/issue-358.hpp diff --git a/tests/headers/issue-372.hpp b/bindgen-tests/tests/headers/issue-372.hpp similarity index 79% rename from tests/headers/issue-372.hpp rename to bindgen-tests/tests/headers/issue-372.hpp index de1447769a..7127be2ccb 100644 --- a/tests/headers/issue-372.hpp +++ b/bindgen-tests/tests/headers/issue-372.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --enable-cxx-namespaces --rustified-enum .* +// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*" template class c { a e[b]; }; class d; template class C { c h; }; diff --git a/bindgen-tests/tests/headers/issue-410.hpp b/bindgen-tests/tests/headers/issue-410.hpp new file mode 100644 index 0000000000..d4f3de3d1c --- /dev/null +++ b/bindgen-tests/tests/headers/issue-410.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type JS::Value --rustified-enum ".*" + +namespace JS { +class Value; +} +typedef enum {} JSWhyMagic; +namespace JS { +class Value { +public: + void a(JSWhyMagic); +}; +} diff --git a/tests/headers/issue-446.hpp b/bindgen-tests/tests/headers/issue-446.hpp similarity index 100% rename from tests/headers/issue-446.hpp rename to bindgen-tests/tests/headers/issue-446.hpp diff --git a/tests/headers/issue-447.hpp b/bindgen-tests/tests/headers/issue-447.hpp similarity index 88% rename from tests/headers/issue-447.hpp rename to bindgen-tests/tests/headers/issue-447.hpp index 017838c42f..43765fa9ee 100644 --- a/tests/headers/issue-447.hpp +++ b/bindgen-tests/tests/headers/issue-447.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type JSAutoCompartment -- -std=c++11 +// bindgen-flags: --enable-cxx-namespaces --allowlist-type JSAutoCompartment -- -std=c++11 namespace mozilla { template class a {}; diff --git a/tests/headers/issue-493.hpp b/bindgen-tests/tests/headers/issue-493.hpp similarity index 96% rename from tests/headers/issue-493.hpp rename to bindgen-tests/tests/headers/issue-493.hpp index 280b873631..8b122ceb50 100644 --- a/tests/headers/issue-493.hpp +++ b/bindgen-tests/tests/headers/issue-493.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" template class basic_string { diff --git a/bindgen-tests/tests/headers/issue-511.h b/bindgen-tests/tests/headers/issue-511.h new file mode 100644 index 0000000000..da3643121e --- /dev/null +++ b/bindgen-tests/tests/headers/issue-511.h @@ -0,0 +1,4 @@ +char * a; +const char * b; +char * const c; +const char * const d; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/issue-537-repr-packed-n.h b/bindgen-tests/tests/headers/issue-537-repr-packed-n.h new file mode 100644 index 0000000000..40be004c85 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-537-repr-packed-n.h @@ -0,0 +1,34 @@ +// bindgen-flags: --raw-line '#![cfg(feature = "nightly")]' + +/// This should not be opaque; we can see the attributes and can pack the +/// struct. +struct AlignedToOne { + int i; +} __attribute__ ((packed,aligned(1))); + +/// This should be packed because Rust 1.33 has `#[repr(packed(N))]`. +struct AlignedToTwo { + int i; +} __attribute__ ((packed,aligned(2))); + +#pragma pack(1) + +/// This should not be opaque because although `libclang` doesn't give us the +/// `#pragma pack(1)`, we can detect that alignment is 1 and add +/// `#[repr(packed)]` to the struct ourselves. +struct PackedToOne { + int x; + int y; +}; + +#pragma pack() + +#pragma pack(2) + +/// This should be packed because Rust 1.33 has `#[repr(packed(N))]`. +struct PackedToTwo { + int x; + int y; +}; + +#pragma pack() diff --git a/tests/headers/issue-537.h b/bindgen-tests/tests/headers/issue-537.h similarity index 83% rename from tests/headers/issue-537.h rename to bindgen-tests/tests/headers/issue-537.h index 9a1072a7b6..a773199f09 100644 --- a/tests/headers/issue-537.h +++ b/bindgen-tests/tests/headers/issue-537.h @@ -4,8 +4,8 @@ struct AlignedToOne { int i; } __attribute__ ((packed,aligned(1))); -/// This should be opaque because although we can see the attributes, Rust -/// doesn't have `#[repr(packed = "N")]` yet. +/// This should be opaque because although we can see the attributes, Rust before +/// 1.33 doesn't have `#[repr(packed(N))]`. struct AlignedToTwo { int i; } __attribute__ ((packed,aligned(2))); @@ -25,8 +25,8 @@ struct PackedToOne { #pragma pack(2) /// In this case, even if we can detect the weird alignment triggered by -/// `#pragma pack(2)`, we can't do anything about it because Rust doesn't have -/// `#[repr(packed = "N")]`. Therefore, we must make it opaque. +/// `#pragma pack(2)`, we can't do anything about it because Rust before 1.33 +/// doesn't have `#[repr(packed(N))]`. Therefore, we must make it opaque. struct PackedToTwo { int x; int y; diff --git a/bindgen-tests/tests/headers/issue-544-stylo-creduce-2.hpp b/bindgen-tests/tests/headers/issue-544-stylo-creduce-2.hpp new file mode 100644 index 0000000000..b41b422d1e --- /dev/null +++ b/bindgen-tests/tests/headers/issue-544-stylo-creduce-2.hpp @@ -0,0 +1,15 @@ +// bindgen-flags: -- -std=c++14 + +template +struct Foo { + template using FirstAlias = typename T::Associated; + template using SecondAlias = Foo>; + +#if 0 + // FIXME: This regressed sometime between libclang 9 and 16, though it + // never quite worked properly so... + SecondAlias member; +#else + SecondAlias* member; +#endif +}; diff --git a/tests/headers/issue-544-stylo-creduce.hpp b/bindgen-tests/tests/headers/issue-544-stylo-creduce.hpp similarity index 100% rename from tests/headers/issue-544-stylo-creduce.hpp rename to bindgen-tests/tests/headers/issue-544-stylo-creduce.hpp diff --git a/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp b/bindgen-tests/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp similarity index 89% rename from tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp rename to bindgen-tests/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp index 964b69cb05..297d111291 100644 --- a/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp +++ b/bindgen-tests/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++14 +// bindgen-flags: --rustified-enum ".*" -- -std=c++14 // Generated by C-Reduce, cleaned up and given names for readability. diff --git a/tests/headers/issue-573-layout-test-failures.hpp b/bindgen-tests/tests/headers/issue-573-layout-test-failures.hpp similarity index 100% rename from tests/headers/issue-573-layout-test-failures.hpp rename to bindgen-tests/tests/headers/issue-573-layout-test-failures.hpp diff --git a/tests/headers/issue-574-assertion-failure-in-codegen.hpp b/bindgen-tests/tests/headers/issue-574-assertion-failure-in-codegen.hpp similarity index 100% rename from tests/headers/issue-574-assertion-failure-in-codegen.hpp rename to bindgen-tests/tests/headers/issue-574-assertion-failure-in-codegen.hpp diff --git a/tests/headers/issue-584-stylo-template-analysis-panic.hpp b/bindgen-tests/tests/headers/issue-584-stylo-template-analysis-panic.hpp similarity index 81% rename from tests/headers/issue-584-stylo-template-analysis-panic.hpp rename to bindgen-tests/tests/headers/issue-584-stylo-template-analysis-panic.hpp index 3bf00e5da9..5f11ea3c9c 100644 --- a/tests/headers/issue-584-stylo-template-analysis-panic.hpp +++ b/bindgen-tests/tests/headers/issue-584-stylo-template-analysis-panic.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --blacklist-type RefPtr --whitelist-function 'Servo_.*' --raw-line 'pub type RefPtr = T;' -- -std=c++14 +// bindgen-flags: --blocklist-type RefPtr --allowlist-function 'Servo_.*' --raw-line 'pub type RefPtr = T;' -- -std=c++14 template class RefPtr; class b; class A { diff --git a/tests/headers/issue-638-stylo-cannot-find-T-in-this-scope.hpp b/bindgen-tests/tests/headers/issue-638-stylo-cannot-find-T-in-this-scope.hpp similarity index 100% rename from tests/headers/issue-638-stylo-cannot-find-T-in-this-scope.hpp rename to bindgen-tests/tests/headers/issue-638-stylo-cannot-find-T-in-this-scope.hpp diff --git a/tests/headers/issue-639-typedef-anon-field.hpp b/bindgen-tests/tests/headers/issue-639-typedef-anon-field.hpp similarity index 100% rename from tests/headers/issue-639-typedef-anon-field.hpp rename to bindgen-tests/tests/headers/issue-639-typedef-anon-field.hpp diff --git a/tests/headers/issue-643-inner-struct.h b/bindgen-tests/tests/headers/issue-643-inner-struct.h similarity index 100% rename from tests/headers/issue-643-inner-struct.h rename to bindgen-tests/tests/headers/issue-643-inner-struct.h diff --git a/bindgen-tests/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp b/bindgen-tests/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp new file mode 100644 index 0000000000..8e07a8a0fd --- /dev/null +++ b/bindgen-tests/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --blocklist-type RefPtr --raw-line "#[derive(Clone, Copy, Debug)] pub struct RefPtr(T);" --allowlist-type "HasRefPtr" -- -std=c++14 + +template class RefPtr {}; + +template +class HasRefPtr { + typedef T TypedefOfT; + RefPtr refptr_member; +}; diff --git a/bindgen-tests/tests/headers/issue-648-derive-debug-with-padding.h b/bindgen-tests/tests/headers/issue-648-derive-debug-with-padding.h new file mode 100644 index 0000000000..d54fe374ce --- /dev/null +++ b/bindgen-tests/tests/headers/issue-648-derive-debug-with-padding.h @@ -0,0 +1,21 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq +/** + * We emit a `[u8; 63usize]` padding field for this struct, which cannot derive + * Debug/Hash because 63 is over the hard coded limit. + */ +struct NoDebug { + char c; + // padding of 63 bytes +} __attribute__((__aligned__(64))); + +/** + * This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive + * Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because + * we determine Debug derive-ability before we compute padding, which happens at + * codegen. + */ +struct ShouldDeriveDebugButDoesNot { + char c[32]; + char d; + // padding of 31 bytes +} __attribute__((__aligned__(64))); diff --git a/tests/headers/issue-654-struct-fn-collision.h b/bindgen-tests/tests/headers/issue-654-struct-fn-collision.h similarity index 100% rename from tests/headers/issue-654-struct-fn-collision.h rename to bindgen-tests/tests/headers/issue-654-struct-fn-collision.h diff --git a/tests/headers/issue-662-cannot-find-T-in-this-scope.hpp b/bindgen-tests/tests/headers/issue-662-cannot-find-T-in-this-scope.hpp similarity index 100% rename from tests/headers/issue-662-cannot-find-T-in-this-scope.hpp rename to bindgen-tests/tests/headers/issue-662-cannot-find-T-in-this-scope.hpp diff --git a/bindgen-tests/tests/headers/issue-662-part-2.hpp b/bindgen-tests/tests/headers/issue-662-part-2.hpp new file mode 100644 index 0000000000..1330c34280 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-662-part-2.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --blocklist-type RefPtr --raw-line '#[derive(Clone, Copy, Debug)] pub struct RefPtr(T);' -- --std=c++14 + +// This is pretty much the same as the other issue 662 test case, but this time +// we blocklist RefPtr to exercise the instantiation-of-a-blocklisted-template +// path in the template analysis. + +template class RefPtr {}; +template class nsMainThreadPtrHolder { T a; }; +template class nsMainThreadPtrHandle { + RefPtr> mPtr; +}; diff --git a/bindgen-tests/tests/headers/issue-674-1.hpp b/bindgen-tests/tests/headers/issue-674-1.hpp new file mode 100644 index 0000000000..7fc781c1da --- /dev/null +++ b/bindgen-tests/tests/headers/issue-674-1.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type CapturingContentInfo --opaque-type 'mozilla::Maybe' -- -std=c++14 + +namespace mozilla { +template class Maybe { using ValueType = T; }; +} +struct CapturingContentInfo { + mozilla::Maybe a; +}; diff --git a/bindgen-tests/tests/headers/issue-674-2.hpp b/bindgen-tests/tests/headers/issue-674-2.hpp new file mode 100644 index 0000000000..86d2b6488d --- /dev/null +++ b/bindgen-tests/tests/headers/issue-674-2.hpp @@ -0,0 +1,15 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type StaticRefPtr --opaque-type 'JS::Rooted' -- -std=c++14 + +namespace JS { +template class Rooted { using ElementType = T; }; +} +class c { + JS::Rooted b; +}; +class B { + c a; +}; +template class StaticRefPtr {}; +struct { + StaticRefPtr d; +} e; diff --git a/bindgen-tests/tests/headers/issue-674-3.hpp b/bindgen-tests/tests/headers/issue-674-3.hpp new file mode 100644 index 0000000000..20aa463c9e --- /dev/null +++ b/bindgen-tests/tests/headers/issue-674-3.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type nsCSSValue --opaque-type 'nsRefPtrHashtable' -- -std=c++14 + +template class nsRefPtrHashtable { + typedef PtrType *UserDataType; +}; +struct a { + nsRefPtrHashtable b; +}; +class nsCSSValue { + a c; +}; diff --git a/tests/headers/issue-677-nested-ns-specifier.hpp b/bindgen-tests/tests/headers/issue-677-nested-ns-specifier.hpp similarity index 100% rename from tests/headers/issue-677-nested-ns-specifier.hpp rename to bindgen-tests/tests/headers/issue-677-nested-ns-specifier.hpp diff --git a/tests/headers/issue-691-template-parameter-virtual.hpp b/bindgen-tests/tests/headers/issue-691-template-parameter-virtual.hpp similarity index 100% rename from tests/headers/issue-691-template-parameter-virtual.hpp rename to bindgen-tests/tests/headers/issue-691-template-parameter-virtual.hpp diff --git a/bindgen-tests/tests/headers/issue-710-must-use-type.h b/bindgen-tests/tests/headers/issue-710-must-use-type.h new file mode 100644 index 0000000000..276f636d70 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-710-must-use-type.h @@ -0,0 +1,8 @@ +// bindgen-flags: --must-use-type A + +struct A; + +/**
*/ +struct B; + +struct C; diff --git a/tests/headers/issue-739-pointer-wide-bitfield.h b/bindgen-tests/tests/headers/issue-739-pointer-wide-bitfield.h similarity index 75% rename from tests/headers/issue-739-pointer-wide-bitfield.h rename to bindgen-tests/tests/headers/issue-739-pointer-wide-bitfield.h index 611dab1da0..eeb7ae9c2d 100644 --- a/tests/headers/issue-739-pointer-wide-bitfield.h +++ b/bindgen-tests/tests/headers/issue-739-pointer-wide-bitfield.h @@ -1,3 +1,4 @@ +// bindgen-flags: --raw-line '#![cfg(not(target_os="windows"))]' #define POINTER_WIDTH (sizeof(void*) * 8) struct Foo { diff --git a/bindgen-tests/tests/headers/issue-743.h b/bindgen-tests/tests/headers/issue-743.h new file mode 100644 index 0000000000..1f8e0ccd78 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-743.h @@ -0,0 +1,6 @@ + +struct S { + void *p; + _Bool b; + unsigned u : 16; +}; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/issue-753.h b/bindgen-tests/tests/headers/issue-753.h new file mode 100644 index 0000000000..3a6c82528a --- /dev/null +++ b/bindgen-tests/tests/headers/issue-753.h @@ -0,0 +1,12 @@ +// bindgen-flags: --clang-macro-fallback + +#ifndef ISSUE_753_H +#define ISSUE_753_H + +#define UINT32_C(c) c ## U + +#define CONST UINT32_C(5) +#define OTHER_CONST UINT32_C(6) +#define LARGE_CONST UINT32_C(6 << 8) + +#endif diff --git a/bindgen-tests/tests/headers/issue-769-bad-instantiation-test.hpp b/bindgen-tests/tests/headers/issue-769-bad-instantiation-test.hpp new file mode 100644 index 0000000000..13c6dd1ce6 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-769-bad-instantiation-test.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --enable-cxx-namespaces --allowlist-type Rooted + +template +class Rooted { + T member; +}; + +class AutoValueVector : Rooted { + using Alias = int; + using RootedAlias = Rooted; +}; diff --git a/bindgen-tests/tests/headers/issue-801-opaque-sloppiness.hpp b/bindgen-tests/tests/headers/issue-801-opaque-sloppiness.hpp new file mode 100644 index 0000000000..6b707f4ede --- /dev/null +++ b/bindgen-tests/tests/headers/issue-801-opaque-sloppiness.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --opaque-type "B" --allowlist-type "C" --with-derive-hash --with-derive-partialeq --with-derive-eq + +class A; + +class B { + static A a; +}; + +class C { + B b; +}; diff --git a/tests/headers/issue-807-opaque-types-methods-being-generated.hpp b/bindgen-tests/tests/headers/issue-807-opaque-types-methods-being-generated.hpp similarity index 78% rename from tests/headers/issue-807-opaque-types-methods-being-generated.hpp rename to bindgen-tests/tests/headers/issue-807-opaque-types-methods-being-generated.hpp index 91f221ce23..de98b32a15 100644 --- a/tests/headers/issue-807-opaque-types-methods-being-generated.hpp +++ b/bindgen-tests/tests/headers/issue-807-opaque-types-methods-being-generated.hpp @@ -1,12 +1,12 @@ -// bindgen-flags: --whitelist-type Whitelisted --opaque-type Opaque --with-derive-hash --with-derive-partialeq --with-derive-eq -- -std=c++11 +// bindgen-flags: --allowlist-type Allowlisted --opaque-type Opaque --with-derive-hash --with-derive-partialeq --with-derive-eq -- -std=c++11 -// These types are not explicitly whitelisted, but are reachable through the +// These types are not explicitly allowlisted, but are reachable through the // opaque type. class Pupper {}; class Doggo {}; class SuchWow {}; -// These types are not whitelisted, and would be reachable through `Opaque` if +// These types are not allowlisted, and would be reachable through `Opaque` if // it were not marked opaque, but since it is, there should be no bindings // generated for them. class NoBindingsShouldBeGeneratedForMe1 {}; @@ -31,6 +31,6 @@ class Opaque SuchWow eleven_out_of_ten(); }; -class Whitelisted { +class Allowlisted { Opaque some_member; }; diff --git a/tests/headers/issue-816.h b/bindgen-tests/tests/headers/issue-816.h similarity index 100% rename from tests/headers/issue-816.h rename to bindgen-tests/tests/headers/issue-816.h diff --git a/tests/headers/issue-820-unused-template-param-in-alias.hpp b/bindgen-tests/tests/headers/issue-820-unused-template-param-in-alias.hpp similarity index 100% rename from tests/headers/issue-820-unused-template-param-in-alias.hpp rename to bindgen-tests/tests/headers/issue-820-unused-template-param-in-alias.hpp diff --git a/tests/headers/issue-826-generating-methods-when-asked-not-to.hpp b/bindgen-tests/tests/headers/issue-826-generating-methods-when-asked-not-to.hpp similarity index 100% rename from tests/headers/issue-826-generating-methods-when-asked-not-to.hpp rename to bindgen-tests/tests/headers/issue-826-generating-methods-when-asked-not-to.hpp diff --git a/bindgen-tests/tests/headers/issue-833-1.hpp b/bindgen-tests/tests/headers/issue-833-1.hpp new file mode 100644 index 0000000000..d66ee01fa7 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-833-1.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --generate functions --allowlist-function func --raw-line "#[repr(C)] pub struct nsTArray { pub hdr: *const () }" + +template +class nsTArray { + static T* sFoo; +}; + +extern "C" nsTArray* func(); diff --git a/tests/headers/issue-833-2.hpp b/bindgen-tests/tests/headers/issue-833-2.hpp similarity index 100% rename from tests/headers/issue-833-2.hpp rename to bindgen-tests/tests/headers/issue-833-2.hpp diff --git a/bindgen-tests/tests/headers/issue-833.hpp b/bindgen-tests/tests/headers/issue-833.hpp new file mode 100644 index 0000000000..f8b708bf16 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-833.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --generate functions --allowlist-function func --raw-line "#[repr(C)] pub struct nsTArray { pub hdr: *const T }" + +template +class nsTArray { + T* mHeader; +}; + +extern "C" nsTArray* func(); diff --git a/bindgen-tests/tests/headers/issue-834.hpp b/bindgen-tests/tests/headers/issue-834.hpp new file mode 100644 index 0000000000..6479701262 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-834.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: --allowlist-type U --generate types + +struct T {}; +struct U { + void test(T a); +}; diff --git a/tests/headers/issue-848-replacement-system-include.hpp b/bindgen-tests/tests/headers/issue-848-replacement-system-include.hpp similarity index 100% rename from tests/headers/issue-848-replacement-system-include.hpp rename to bindgen-tests/tests/headers/issue-848-replacement-system-include.hpp diff --git a/tests/headers/issue-848/an-include.h b/bindgen-tests/tests/headers/issue-848/an-include.h similarity index 100% rename from tests/headers/issue-848/an-include.h rename to bindgen-tests/tests/headers/issue-848/an-include.h diff --git a/bindgen-tests/tests/headers/issue-888-enum-var-decl-jump.hpp b/bindgen-tests/tests/headers/issue-888-enum-var-decl-jump.hpp new file mode 100644 index 0000000000..fa4ba56ba4 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-888-enum-var-decl-jump.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*" + +namespace Halide { +struct Type; +} +typedef enum {} a; +namespace Halide { +struct Type { + static a b; +}; +} diff --git a/bindgen-tests/tests/headers/issue-944-derive-copy-and-blocklisting.hpp b/bindgen-tests/tests/headers/issue-944-derive-copy-and-blocklisting.hpp new file mode 100644 index 0000000000..5e94dfabd4 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-944-derive-copy-and-blocklisting.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --blocklist-type BlocklistMe --raw-line 'pub struct BlocklistMe(u8);' + +struct BlocklistMe {}; + +/** + * Because this type contains a blocklisted type, it should not derive Copy. + */ +struct ShouldNotBeCopy { + BlocklistMe a; +}; diff --git a/tests/headers/issue-946.h b/bindgen-tests/tests/headers/issue-946.h similarity index 100% rename from tests/headers/issue-946.h rename to bindgen-tests/tests/headers/issue-946.h diff --git a/tests/headers/issue_311.hpp b/bindgen-tests/tests/headers/issue_311.hpp similarity index 100% rename from tests/headers/issue_311.hpp rename to bindgen-tests/tests/headers/issue_311.hpp diff --git a/tests/headers/issue_315.hpp b/bindgen-tests/tests/headers/issue_315.hpp similarity index 100% rename from tests/headers/issue_315.hpp rename to bindgen-tests/tests/headers/issue_315.hpp diff --git a/tests/headers/jsval_layout_opaque.hpp b/bindgen-tests/tests/headers/jsval_layout_opaque.hpp similarity index 99% rename from tests/headers/jsval_layout_opaque.hpp rename to bindgen-tests/tests/headers/jsval_layout_opaque.hpp index 7a1957cffd..ef13b85b25 100644 --- a/tests/headers/jsval_layout_opaque.hpp +++ b/bindgen-tests/tests/headers/jsval_layout_opaque.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" // bindgen-flags: -- -std=c++11 /** diff --git a/tests/headers/keywords.h b/bindgen-tests/tests/headers/keywords.h similarity index 87% rename from tests/headers/keywords.h rename to bindgen-tests/tests/headers/keywords.h index 8699ce5f22..49924193c7 100644 --- a/tests/headers/keywords.h +++ b/bindgen-tests/tests/headers/keywords.h @@ -10,11 +10,18 @@ int f32; int f64; int usize; int isize; +int bool; +int str; +int dyn; + int as; +int async; +int await; int box; int crate; int false; int fn; +int gen; int impl; int in; int let; @@ -30,6 +37,7 @@ int Self; int super; int trait; int true; +int try; int type; int unsafe; int use; diff --git a/bindgen-tests/tests/headers/layout.h b/bindgen-tests/tests/headers/layout.h new file mode 100644 index 0000000000..06b7165ab9 --- /dev/null +++ b/bindgen-tests/tests/headers/layout.h @@ -0,0 +1,11 @@ +// FIXME: https://github.com/rust-lang/rust-bindgen/issues/1498 + + +#if 0 +struct header +{ + char proto; + unsigned int size __attribute__ ((packed)); + unsigned char data[] __attribute__ ((aligned(8))); +} __attribute__ ((aligned, packed)); +#endif diff --git a/tests/headers/layout_align.h b/bindgen-tests/tests/headers/layout_align.h similarity index 100% rename from tests/headers/layout_align.h rename to bindgen-tests/tests/headers/layout_align.h diff --git a/tests/headers/layout_arp.h b/bindgen-tests/tests/headers/layout_arp.h similarity index 100% rename from tests/headers/layout_arp.h rename to bindgen-tests/tests/headers/layout_arp.h diff --git a/tests/headers/layout_array.h b/bindgen-tests/tests/headers/layout_array.h similarity index 100% rename from tests/headers/layout_array.h rename to bindgen-tests/tests/headers/layout_array.h diff --git a/tests/headers/layout_array_too_long.h b/bindgen-tests/tests/headers/layout_array_too_long.h similarity index 97% rename from tests/headers/layout_array_too_long.h rename to bindgen-tests/tests/headers/layout_array_too_long.h index 1d8b1b63e7..d0d34ba038 100644 --- a/tests/headers/layout_array_too_long.h +++ b/bindgen-tests/tests/headers/layout_array_too_long.h @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum ".*" typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; diff --git a/tests/headers/layout_cmdline_token.h b/bindgen-tests/tests/headers/layout_cmdline_token.h similarity index 94% rename from tests/headers/layout_cmdline_token.h rename to bindgen-tests/tests/headers/layout_cmdline_token.h index 68dd53b837..da1bfc2e7a 100644 --- a/tests/headers/layout_cmdline_token.h +++ b/bindgen-tests/tests/headers/layout_cmdline_token.h @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" /** * Stores a pointer to the ops struct, and the offset: the place to @@ -61,4 +61,4 @@ struct cmdline_token_num { struct cmdline_token_hdr hdr; struct cmdline_token_num_data num_data; }; -typedef struct cmdline_token_num cmdline_parse_token_num_t; \ No newline at end of file +typedef struct cmdline_token_num cmdline_parse_token_num_t; diff --git a/tests/headers/layout_eth_conf.h b/bindgen-tests/tests/headers/layout_eth_conf.h similarity index 98% rename from tests/headers/layout_eth_conf.h rename to bindgen-tests/tests/headers/layout_eth_conf.h index 71a430bfae..ec1a691985 100644 --- a/tests/headers/layout_eth_conf.h +++ b/bindgen-tests/tests/headers/layout_eth_conf.h @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; @@ -139,7 +139,7 @@ enum rte_eth_nb_pools { * of an Ethernet port. * * Using this feature, packets are routed to a pool of queues, based - * on the vlan id in the vlan tag, and then to a specific queue within + * on the vlan ID in the vlan tag, and then to a specific queue within * that pool, using the user priority vlan tag field. * * A default pool may be used, if desired, to route all traffic which @@ -151,7 +151,7 @@ struct rte_eth_vmdq_dcb_conf { uint8_t default_pool; /**< The default pool, if applicable */ uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ struct { - uint16_t vlan_id; /**< The vlan id of the received frame */ + uint16_t vlan_id; /**< The vlan ID of the received frame */ uint64_t pools; /**< Bitmask of pools for packet rx */ } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ uint8_t dcb_tc[ETH_DCB_NUM_USER_PRIORITIES]; @@ -189,7 +189,7 @@ struct rte_eth_vmdq_rx_conf { uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ uint32_t rx_mode; /**< Flags from ETH_VMDQ_ACCEPT_* */ struct { - uint16_t vlan_id; /**< The vlan id of the received frame */ + uint16_t vlan_id; /**< The vlan ID of the received frame */ uint64_t pools; /**< Bitmask of pools for packet rx */ } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ }; diff --git a/tests/headers/layout_kni_mbuf.h b/bindgen-tests/tests/headers/layout_kni_mbuf.h similarity index 99% rename from tests/headers/layout_kni_mbuf.h rename to bindgen-tests/tests/headers/layout_kni_mbuf.h index ff161144a3..148cb7df95 100644 --- a/tests/headers/layout_kni_mbuf.h +++ b/bindgen-tests/tests/headers/layout_kni_mbuf.h @@ -1,4 +1,3 @@ - #define RTE_CACHE_LINE_MIN_SIZE 64 /**< Minimum Cache line size. */ #define RTE_CACHE_LINE_SIZE 64 diff --git a/tests/headers/layout_large_align_field.h b/bindgen-tests/tests/headers/layout_large_align_field.h similarity index 98% rename from tests/headers/layout_large_align_field.h rename to bindgen-tests/tests/headers/layout_large_align_field.h index 5e87c2a1c4..f292bb70dc 100644 --- a/tests/headers/layout_large_align_field.h +++ b/bindgen-tests/tests/headers/layout_large_align_field.h @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" typedef unsigned char uint8_t; typedef unsigned short uint16_t; diff --git a/tests/headers/layout_mbuf.h b/bindgen-tests/tests/headers/layout_mbuf.h similarity index 100% rename from tests/headers/layout_mbuf.h rename to bindgen-tests/tests/headers/layout_mbuf.h diff --git a/bindgen-tests/tests/headers/long_double.h b/bindgen-tests/tests/headers/long_double.h new file mode 100644 index 0000000000..341be37164 --- /dev/null +++ b/bindgen-tests/tests/headers/long_double.h @@ -0,0 +1,3 @@ +struct foo { + long double bar; +}; diff --git a/tests/headers/macro-expr-basic.h b/bindgen-tests/tests/headers/macro-expr-basic.h similarity index 100% rename from tests/headers/macro-expr-basic.h rename to bindgen-tests/tests/headers/macro-expr-basic.h diff --git a/tests/headers/macro-expr-uncommon-token.h b/bindgen-tests/tests/headers/macro-expr-uncommon-token.h similarity index 100% rename from tests/headers/macro-expr-uncommon-token.h rename to bindgen-tests/tests/headers/macro-expr-uncommon-token.h diff --git a/tests/headers/macro-redef.h b/bindgen-tests/tests/headers/macro-redef.h similarity index 100% rename from tests/headers/macro-redef.h rename to bindgen-tests/tests/headers/macro-redef.h diff --git a/tests/headers/macro_const.h b/bindgen-tests/tests/headers/macro_const.h similarity index 90% rename from tests/headers/macro_const.h rename to bindgen-tests/tests/headers/macro_const.h index c28a3f6bc8..7c5aa43806 100644 --- a/tests/headers/macro_const.h +++ b/bindgen-tests/tests/headers/macro_const.h @@ -3,5 +3,6 @@ #define CHARR '\0' #define FLOAT 5.09f #define FLOAT_EXPR (5 / 1000.0f) +#define LONG 3L #define INVALID_UTF8 "\xf0\x28\x8c\x28" diff --git a/bindgen-tests/tests/headers/maddness-is-avoidable.hpp b/bindgen-tests/tests/headers/maddness-is-avoidable.hpp new file mode 100644 index 0000000000..47a7ffbfac --- /dev/null +++ b/bindgen-tests/tests/headers/maddness-is-avoidable.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --blocklist-type RefPtr_Proxy_member_function + +template +class RefPtr { + template + class Proxy { + typedef R (T::*member_function)(Args...); + }; +}; diff --git a/tests/headers/mangling-ios.h b/bindgen-tests/tests/headers/mangling-ios.h similarity index 100% rename from tests/headers/mangling-ios.h rename to bindgen-tests/tests/headers/mangling-ios.h diff --git a/tests/headers/mangling-linux32.hpp b/bindgen-tests/tests/headers/mangling-linux32.hpp similarity index 100% rename from tests/headers/mangling-linux32.hpp rename to bindgen-tests/tests/headers/mangling-linux32.hpp diff --git a/tests/headers/mangling-linux64.hpp b/bindgen-tests/tests/headers/mangling-linux64.hpp similarity index 100% rename from tests/headers/mangling-linux64.hpp rename to bindgen-tests/tests/headers/mangling-linux64.hpp diff --git a/tests/headers/mangling-macos.hpp b/bindgen-tests/tests/headers/mangling-macos.hpp similarity index 100% rename from tests/headers/mangling-macos.hpp rename to bindgen-tests/tests/headers/mangling-macos.hpp diff --git a/bindgen-tests/tests/headers/mangling-win32.hpp b/bindgen-tests/tests/headers/mangling-win32.hpp new file mode 100644 index 0000000000..76a7e664ed --- /dev/null +++ b/bindgen-tests/tests/headers/mangling-win32.hpp @@ -0,0 +1,18 @@ +// bindgen-flags: --raw-line '#![cfg(target = "i686-pc-windows-msvc")]' -- --target=i686-pc-win32 + +extern "C" void foo(); + +struct Foo { + static bool sBar; +}; + +// Also test some x86 Windows specific calling conventions that have their own +// special mangling +extern "C" { + int _fastcall fast_call_func_no_args(); + // This will result in a suffix with more than one character (i.e. `@12`) + int _fastcall fast_call_func_many_args(int,int,int); + int _stdcall std_call_func_no_args(); + // This will result in a suffix with more than one character (i.e. `@12`) + int _stdcall std_call_func_many_args(int,int,int); +} diff --git a/tests/headers/mangling-win64.hpp b/bindgen-tests/tests/headers/mangling-win64.hpp similarity index 100% rename from tests/headers/mangling-win64.hpp rename to bindgen-tests/tests/headers/mangling-win64.hpp diff --git a/bindgen-tests/tests/headers/merge_extern_blocks_post_1_82.hpp b/bindgen-tests/tests/headers/merge_extern_blocks_post_1_82.hpp new file mode 100644 index 0000000000..080979f17b --- /dev/null +++ b/bindgen-tests/tests/headers/merge_extern_blocks_post_1_82.hpp @@ -0,0 +1,14 @@ +// bindgen-flags: --merge-extern-blocks --enable-cxx-namespaces --rust-target=1.82 -- --target=x86_64-unknown-linux +int foo(); +typedef struct Point { + int x; +} Point; +int bar(); + +namespace ns { + int foo(); + typedef struct Point { + int x; + } Point; + int bar(); +} diff --git a/bindgen-tests/tests/headers/merge_extern_blocks_pre_1_82.hpp b/bindgen-tests/tests/headers/merge_extern_blocks_pre_1_82.hpp new file mode 100644 index 0000000000..779abf174b --- /dev/null +++ b/bindgen-tests/tests/headers/merge_extern_blocks_pre_1_82.hpp @@ -0,0 +1,14 @@ +// bindgen-flags: --merge-extern-blocks --enable-cxx-namespaces --rust-target=1.81 -- --target=x86_64-unknown-linux +int foo(); +typedef struct Point { + int x; +} Point; +int bar(); + +namespace ns { + int foo(); + typedef struct Point { + int x; + } Point; + int bar(); +} diff --git a/tests/headers/method-mangling.hpp b/bindgen-tests/tests/headers/method-mangling.hpp similarity index 100% rename from tests/headers/method-mangling.hpp rename to bindgen-tests/tests/headers/method-mangling.hpp diff --git a/tests/headers/module-whitelisted.hpp b/bindgen-tests/tests/headers/module-allowlisted.hpp similarity index 100% rename from tests/headers/module-whitelisted.hpp rename to bindgen-tests/tests/headers/module-allowlisted.hpp diff --git a/tests/headers/msvc-no-usr.hpp b/bindgen-tests/tests/headers/msvc-no-usr.hpp similarity index 100% rename from tests/headers/msvc-no-usr.hpp rename to bindgen-tests/tests/headers/msvc-no-usr.hpp diff --git a/tests/headers/multiple-inherit-empty-correct-layout.hpp b/bindgen-tests/tests/headers/multiple-inherit-empty-correct-layout.hpp similarity index 100% rename from tests/headers/multiple-inherit-empty-correct-layout.hpp rename to bindgen-tests/tests/headers/multiple-inherit-empty-correct-layout.hpp diff --git a/tests/headers/mutable.hpp b/bindgen-tests/tests/headers/mutable.hpp similarity index 100% rename from tests/headers/mutable.hpp rename to bindgen-tests/tests/headers/mutable.hpp diff --git a/bindgen-tests/tests/headers/namespace.hpp b/bindgen-tests/tests/headers/namespace.hpp new file mode 100644 index 0000000000..7e4197da5f --- /dev/null +++ b/bindgen-tests/tests/headers/namespace.hpp @@ -0,0 +1,51 @@ +// bindgen-flags: --enable-cxx-namespaces --module-raw-line root::whatever 'pub type whatever_other_thing_t = whatever_int_t;' + +void top_level(); + +namespace whatever { + typedef int whatever_int_t; + + void in_whatever(); +} + +namespace { + namespace empty {} + + struct A { + whatever::whatever_int_t b; + }; +} + +template +class C: public A { + T m_c; + T* m_c_ptr; + T m_c_arr[10]; +}; + +template<> +class C; + +namespace w { + typedef unsigned int whatever_int_t; + + template + class D { + C m_c; + }; + + whatever_int_t heh(); // this should return w::whatever_int_t, and not whatever::whatever_int_t + + C foo(); + + C barr(); // <- This is the problematic one +} + +#define NAMESPACE foobar +namespace NAMESPACE { + void foo(); +} + +#include "namespace/nsbegin.h" +void bar(); +#include "namespace/nsend.h" diff --git a/bindgen-tests/tests/headers/namespace/nsbegin.h b/bindgen-tests/tests/headers/namespace/nsbegin.h new file mode 100644 index 0000000000..47a51c93b8 --- /dev/null +++ b/bindgen-tests/tests/headers/namespace/nsbegin.h @@ -0,0 +1 @@ +namespace faraway { diff --git a/bindgen-tests/tests/headers/namespace/nsdefine.h b/bindgen-tests/tests/headers/namespace/nsdefine.h new file mode 100644 index 0000000000..6504fa9f0a --- /dev/null +++ b/bindgen-tests/tests/headers/namespace/nsdefine.h @@ -0,0 +1,4 @@ +#pragma once + +#define BEGIN_NAMESPACE namespace repro { inline namespace __1 { +#define END_NAMESPACE } } diff --git a/bindgen-tests/tests/headers/namespace/nsend.h b/bindgen-tests/tests/headers/namespace/nsend.h new file mode 100644 index 0000000000..5c34318c21 --- /dev/null +++ b/bindgen-tests/tests/headers/namespace/nsend.h @@ -0,0 +1 @@ +} diff --git a/bindgen-tests/tests/headers/nested-class-field.hpp b/bindgen-tests/tests/headers/nested-class-field.hpp new file mode 100644 index 0000000000..295ebe8129 --- /dev/null +++ b/bindgen-tests/tests/headers/nested-class-field.hpp @@ -0,0 +1,7 @@ +class A { + class I; +}; + +class A::I { + int i; +}; diff --git a/bindgen-tests/tests/headers/nested-template-typedef.hpp b/bindgen-tests/tests/headers/nested-template-typedef.hpp new file mode 100644 index 0000000000..8c83de5bae --- /dev/null +++ b/bindgen-tests/tests/headers/nested-template-typedef.hpp @@ -0,0 +1,8 @@ +template +class Foo { +public: + template + struct Bar { + typedef Foo FooU; + }; +}; diff --git a/tests/headers/nested.hpp b/bindgen-tests/tests/headers/nested.hpp similarity index 100% rename from tests/headers/nested.hpp rename to bindgen-tests/tests/headers/nested.hpp diff --git a/tests/headers/nested_vtable.hpp b/bindgen-tests/tests/headers/nested_vtable.hpp similarity index 100% rename from tests/headers/nested_vtable.hpp rename to bindgen-tests/tests/headers/nested_vtable.hpp diff --git a/tests/headers/nested_within_namespace.hpp b/bindgen-tests/tests/headers/nested_within_namespace.hpp similarity index 100% rename from tests/headers/nested_within_namespace.hpp rename to bindgen-tests/tests/headers/nested_within_namespace.hpp diff --git a/bindgen-tests/tests/headers/new-type-alias.h b/bindgen-tests/tests/headers/new-type-alias.h new file mode 100644 index 0000000000..73de94884c --- /dev/null +++ b/bindgen-tests/tests/headers/new-type-alias.h @@ -0,0 +1,22 @@ +// bindgen-flags: --new-type-alias (Foo|Bar|Baz|Bang) + +// Fake stdint.h and stdbool.h +typedef __UINT64_TYPE__ uint64_t; +#define bool _Bool +#define true 1 + +typedef uint64_t Foo; +static const Foo Foo_A = 1; + +typedef char Bar; +static const Bar Bar_A = 'a'; + +typedef float Baz; +static const Baz Baz_A = 3.25; + +typedef bool Bang; +static const Bang Bang_A = true; + +// Not wrapped +typedef uint64_t Boom; +static const Boom Boom_A = 2; diff --git a/bindgen-tests/tests/headers/newtype-enum.hpp b/bindgen-tests/tests/headers/newtype-enum.hpp new file mode 100644 index 0000000000..e711ed85bc --- /dev/null +++ b/bindgen-tests/tests/headers/newtype-enum.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --newtype-enum "Foo" -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; diff --git a/bindgen-tests/tests/headers/newtype-global-enum.hpp b/bindgen-tests/tests/headers/newtype-global-enum.hpp new file mode 100644 index 0000000000..c10825fdcf --- /dev/null +++ b/bindgen-tests/tests/headers/newtype-global-enum.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --newtype-global-enum "Foo" -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; diff --git a/tests/headers/no-comments.h b/bindgen-tests/tests/headers/no-comments.h similarity index 100% rename from tests/headers/no-comments.h rename to bindgen-tests/tests/headers/no-comments.h diff --git a/tests/headers/no-derive-debug.h b/bindgen-tests/tests/headers/no-derive-debug.h similarity index 82% rename from tests/headers/no-derive-debug.h rename to bindgen-tests/tests/headers/no-derive-debug.h index c780d2d8f8..d11ca0ad92 100644 --- a/tests/headers/no-derive-debug.h +++ b/bindgen-tests/tests/headers/no-derive-debug.h @@ -1,11 +1,11 @@ -// bindgen-flags: --no-derive-debug --blacklist-type foo --raw-line "#[repr(C)] #[derive(Copy, Clone, Default)] pub struct foo { bar: ::std::os::raw::c_int, }" +// bindgen-flags: --no-derive-debug --blocklist-type foo --raw-line "#[repr(C)] #[derive(Copy, Clone, Default)] pub struct foo { bar: ::std::os::raw::c_int, }" struct foo { int bar; }; /** - * bar should compile. It will normally derive debug, but our blacklist of foo + * bar should compile. It will normally derive debug, but our blocklist of foo * and replacement for another type that doesn't implement it would prevent it * from building if --no-derive-debug didn't work. */ diff --git a/tests/headers/no-derive-default.h b/bindgen-tests/tests/headers/no-derive-default.h similarity index 82% rename from tests/headers/no-derive-default.h rename to bindgen-tests/tests/headers/no-derive-default.h index 207b93b62f..d184ee3a98 100644 --- a/tests/headers/no-derive-default.h +++ b/bindgen-tests/tests/headers/no-derive-default.h @@ -1,11 +1,11 @@ -// bindgen-flags: --no-derive-default --blacklist-type foo --raw-line "#[repr(C)] #[derive(Copy, Clone, Debug)] pub struct foo { bar: ::std::os::raw::c_int, }" +// bindgen-flags: --no-derive-default --blocklist-type foo --raw-line "#[repr(C)] #[derive(Copy, Clone, Debug)] pub struct foo { bar: ::std::os::raw::c_int, }" struct foo { int bar; }; /** - * bar should compile. It will normally derive default, but our blacklist of foo + * bar should compile. It will normally derive default, but our blocklist of foo * and replacement for another type that doesn't implement it would prevent it * from building if --no-derive-default didn't work. */ diff --git a/bindgen-tests/tests/headers/no-hash-allowlisted.hpp b/bindgen-tests/tests/headers/no-hash-allowlisted.hpp new file mode 100644 index 0000000000..0f60817da6 --- /dev/null +++ b/bindgen-tests/tests/headers/no-hash-allowlisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-hash --allowlist-type "NoHash" --no-hash "NoHash" + +class NoHash { + int i; +}; diff --git a/tests/headers/no-hash-opaque.hpp b/bindgen-tests/tests/headers/no-hash-opaque.hpp similarity index 100% rename from tests/headers/no-hash-opaque.hpp rename to bindgen-tests/tests/headers/no-hash-opaque.hpp diff --git a/bindgen-tests/tests/headers/no-partialeq-allowlisted.hpp b/bindgen-tests/tests/headers/no-partialeq-allowlisted.hpp new file mode 100644 index 0000000000..ced1b42a7b --- /dev/null +++ b/bindgen-tests/tests/headers/no-partialeq-allowlisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-partialeq --allowlist-type "NoPartialEq" --no-partialeq "NoPartialEq" + +class NoPartialEq { + int i; +}; diff --git a/tests/headers/no-partialeq-opaque.hpp b/bindgen-tests/tests/headers/no-partialeq-opaque.hpp similarity index 100% rename from tests/headers/no-partialeq-opaque.hpp rename to bindgen-tests/tests/headers/no-partialeq-opaque.hpp diff --git a/bindgen-tests/tests/headers/no-recursive-allowlisting.h b/bindgen-tests/tests/headers/no-recursive-allowlisting.h new file mode 100644 index 0000000000..1c6617110b --- /dev/null +++ b/bindgen-tests/tests/headers/no-recursive-allowlisting.h @@ -0,0 +1,7 @@ +// bindgen-flags: --no-recursive-allowlist --allowlist-type "Foo" --raw-line "pub enum Bar {}" --rustified-enum ".*" + +struct Bar; + +struct Foo { + struct Bar* baz; +}; diff --git a/tests/headers/no-std.h b/bindgen-tests/tests/headers/no-std.h similarity index 82% rename from tests/headers/no-std.h rename to bindgen-tests/tests/headers/no-std.h index 9248cc3dd5..d98abceddf 100644 --- a/tests/headers/no-std.h +++ b/bindgen-tests/tests/headers/no-std.h @@ -1,4 +1,4 @@ -// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }" --rustified-enum .* +// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }" --rustified-enum ".*" struct foo { int a, b; void* bar; diff --git a/tests/headers/no_copy.hpp b/bindgen-tests/tests/headers/no_copy.hpp similarity index 100% rename from tests/headers/no_copy.hpp rename to bindgen-tests/tests/headers/no_copy.hpp diff --git a/bindgen-tests/tests/headers/no_copy_allowlisted.hpp b/bindgen-tests/tests/headers/no_copy_allowlisted.hpp new file mode 100644 index 0000000000..f3b922cae1 --- /dev/null +++ b/bindgen-tests/tests/headers/no_copy_allowlisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --allowlist-type "NoCopy" --no-copy "NoCopy" + +class NoCopy { + int i; +}; diff --git a/tests/headers/no_copy_opaque.hpp b/bindgen-tests/tests/headers/no_copy_opaque.hpp similarity index 100% rename from tests/headers/no_copy_opaque.hpp rename to bindgen-tests/tests/headers/no_copy_opaque.hpp diff --git a/bindgen-tests/tests/headers/no_debug.hpp b/bindgen-tests/tests/headers/no_debug.hpp new file mode 100644 index 0000000000..2017f75da4 --- /dev/null +++ b/bindgen-tests/tests/headers/no_debug.hpp @@ -0,0 +1,6 @@ + +/**
*/ +template +class DebugButWait { + int whatever; +}; diff --git a/bindgen-tests/tests/headers/no_debug_allowlisted.hpp b/bindgen-tests/tests/headers/no_debug_allowlisted.hpp new file mode 100644 index 0000000000..3e3633e475 --- /dev/null +++ b/bindgen-tests/tests/headers/no_debug_allowlisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --allowlist-type "NoDebug" --no-debug "NoDebug" + +class NoDebug { + int i; +}; diff --git a/bindgen-tests/tests/headers/no_debug_bypass_impl_debug.hpp b/bindgen-tests/tests/headers/no_debug_bypass_impl_debug.hpp new file mode 100644 index 0000000000..a586441088 --- /dev/null +++ b/bindgen-tests/tests/headers/no_debug_bypass_impl_debug.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --no-debug "NoDebug" --impl-debug + +template +class Generic { + T t[40]; +}; + +template +class NoDebug { + T t[40]; +}; diff --git a/bindgen-tests/tests/headers/no_debug_opaque.hpp b/bindgen-tests/tests/headers/no_debug_opaque.hpp new file mode 100644 index 0000000000..d5dc18f773 --- /dev/null +++ b/bindgen-tests/tests/headers/no_debug_opaque.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --opaque-type "NoDebug" --no-debug "NoDebug" + +class NoDebug { + int i; +}; diff --git a/bindgen-tests/tests/headers/no_default.hpp b/bindgen-tests/tests/headers/no_default.hpp new file mode 100644 index 0000000000..79d25fbdc2 --- /dev/null +++ b/bindgen-tests/tests/headers/no_default.hpp @@ -0,0 +1,11 @@ + +/**
*/ +template +class DefaultButWait { + int whatever; +}; + +template +class DefaultButWaitDerived { + DefaultButWait whatever; +}; diff --git a/bindgen-tests/tests/headers/no_default_allowlisted.hpp b/bindgen-tests/tests/headers/no_default_allowlisted.hpp new file mode 100644 index 0000000000..8a604081f7 --- /dev/null +++ b/bindgen-tests/tests/headers/no_default_allowlisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --allowlist-type "NoDefault" --no-default "NoDefault" + +class NoDefault { + int i; +}; diff --git a/bindgen-tests/tests/headers/no_default_bypass_derive_default.hpp b/bindgen-tests/tests/headers/no_default_bypass_derive_default.hpp new file mode 100644 index 0000000000..0f8339062f --- /dev/null +++ b/bindgen-tests/tests/headers/no_default_bypass_derive_default.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --no-default "NoDefault" + +template +class Generic { + T t[40]; +}; + +template +class NoDefault { + T t[40]; +}; diff --git a/bindgen-tests/tests/headers/no_default_opaque.hpp b/bindgen-tests/tests/headers/no_default_opaque.hpp new file mode 100644 index 0000000000..3245d8f93c --- /dev/null +++ b/bindgen-tests/tests/headers/no_default_opaque.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --opaque-type "NoDefault" --no-default "NoDefault" + +class NoDefault { + int i; +}; diff --git a/bindgen-tests/tests/headers/no_size_t_is_usize.h b/bindgen-tests/tests/headers/no_size_t_is_usize.h new file mode 100644 index 0000000000..d4370baf9f --- /dev/null +++ b/bindgen-tests/tests/headers/no_size_t_is_usize.h @@ -0,0 +1,10 @@ +// bindgen-flags: --no-size_t-is-usize + +typedef unsigned long size_t; +typedef long ssize_t; + +struct A { + size_t len; + ssize_t offset; + struct A* next; +}; diff --git a/tests/headers/non-type-params.hpp b/bindgen-tests/tests/headers/non-type-params.hpp similarity index 100% rename from tests/headers/non-type-params.hpp rename to bindgen-tests/tests/headers/non-type-params.hpp diff --git a/bindgen-tests/tests/headers/noreturn.hpp b/bindgen-tests/tests/headers/noreturn.hpp new file mode 100644 index 0000000000..bf9d58c7fa --- /dev/null +++ b/bindgen-tests/tests/headers/noreturn.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: --enable-function-attribute-detection -- -std=c++11 +_Noreturn void f(void); +__attribute__((noreturn)) void g(void); +[[noreturn]] void h(void); +void i(__attribute__((noreturn)) void (*arg)(void)); +__attribute__((noreturn)) void j(__attribute__((noreturn)) void (*arg)(void)); diff --git a/tests/headers/nsBaseHashtable.hpp b/bindgen-tests/tests/headers/nsBaseHashtable.hpp similarity index 100% rename from tests/headers/nsBaseHashtable.hpp rename to bindgen-tests/tests/headers/nsBaseHashtable.hpp diff --git a/tests/headers/nsStyleAutoArray.hpp b/bindgen-tests/tests/headers/nsStyleAutoArray.hpp similarity index 97% rename from tests/headers/nsStyleAutoArray.hpp rename to bindgen-tests/tests/headers/nsStyleAutoArray.hpp index 2a0bc21623..3049ea210c 100644 --- a/tests/headers/nsStyleAutoArray.hpp +++ b/bindgen-tests/tests/headers/nsStyleAutoArray.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" template class nsTArray { diff --git a/bindgen-tests/tests/headers/objc_allowlist.h b/bindgen-tests/tests/headers/objc_allowlist.h new file mode 100644 index 0000000000..b5406d0adf --- /dev/null +++ b/bindgen-tests/tests/headers/objc_allowlist.h @@ -0,0 +1,24 @@ +// bindgen-flags: --allowlist-type IAllowlistMe --allowlist-type AllowlistMe_InterestingCategory -- -x objective-c +// bindgen-osx-only + + +// Protocol should be included, since it is used by the AllowlistMe +@protocol SomeProtocol +-(void)protocolMethod; ++(void)protocolClassMethod; +@end + +// The allowlisted item +@interface AllowlistMe +-(void)method; ++(void)classMethod; +@end + +// This was also explicitly allowlisted +@interface AllowlistMe (InterestingCategory) +@end + +// This was not automatically allowlisted +@interface AllowlistMe (IgnoredCategory) +@end + diff --git a/bindgen-tests/tests/headers/objc_blocklist.h b/bindgen-tests/tests/headers/objc_blocklist.h new file mode 100644 index 0000000000..605f2993cf --- /dev/null +++ b/bindgen-tests/tests/headers/objc_blocklist.h @@ -0,0 +1,9 @@ +// bindgen-flags: --objc-extern-crate --blocklist-item ISomeClass::class_ambiguouslyBlockedMethod --blocklist-item ISomeClass::blockedInstanceMethod -- -x objective-c +// bindgen-osx-only + +@interface SomeClass ++ (void)ambiguouslyBlockedMethod; +- (void)ambiguouslyBlockedMethod; +- (void)instanceMethod; +- (void)blockedInstanceMethod; +@end diff --git a/bindgen-tests/tests/headers/objc_category.h b/bindgen-tests/tests/headers/objc_category.h new file mode 100644 index 0000000000..b8e60d5fa9 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_category.h @@ -0,0 +1,10 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +-(void)method; +@end + +@interface Foo (BarCategory) +-(void)categoryMethod; +@end diff --git a/bindgen-tests/tests/headers/objc_class.h b/bindgen-tests/tests/headers/objc_class.h new file mode 100644 index 0000000000..f5ec950750 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_class.h @@ -0,0 +1,10 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@class Foo; + +Foo* fooVar; + +@interface Foo +-(void)method; +@end diff --git a/tests/headers/objc_class_method.h b/bindgen-tests/tests/headers/objc_class_method.h similarity index 82% rename from tests/headers/objc_class_method.h rename to bindgen-tests/tests/headers/objc_class_method.h index ddda742e8a..1a68ed3e6e 100644 --- a/tests/headers/objc_class_method.h +++ b/bindgen-tests/tests/headers/objc_class_method.h @@ -1,4 +1,4 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c +// bindgen-flags: -- -x objective-c // bindgen-osx-only @interface Foo diff --git a/bindgen-tests/tests/headers/objc_escape.h b/bindgen-tests/tests/headers/objc_escape.h new file mode 100644 index 0000000000..2d21bd5481 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_escape.h @@ -0,0 +1,13 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface A +-(void)f:(int)arg1 as:(int)arg2; +-(void)crate:(int)self; +@end + +@interface B + +@property(nonatomic, retain) id type; + +@end diff --git a/bindgen-tests/tests/headers/objc_inheritance.h b/bindgen-tests/tests/headers/objc_inheritance.h new file mode 100644 index 0000000000..985f1597e5 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_inheritance.h @@ -0,0 +1,11 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +@end + +@interface Bar: Foo +@end + +@interface Baz: Bar +@end diff --git a/bindgen-tests/tests/headers/objc_interface.h b/bindgen-tests/tests/headers/objc_interface.h new file mode 100644 index 0000000000..df16e921ec --- /dev/null +++ b/bindgen-tests/tests/headers/objc_interface.h @@ -0,0 +1,8 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +@end + +@protocol bar +@end diff --git a/bindgen-tests/tests/headers/objc_interface_type.h b/bindgen-tests/tests/headers/objc_interface_type.h new file mode 100644 index 0000000000..4667ce2a0c --- /dev/null +++ b/bindgen-tests/tests/headers/objc_interface_type.h @@ -0,0 +1,13 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +@end + +struct FooStruct { + Foo *foo; +}; + +void fooFunc(Foo *foo); + +static const Foo *kFoo; diff --git a/bindgen-tests/tests/headers/objc_method.h b/bindgen-tests/tests/headers/objc_method.h new file mode 100644 index 0000000000..b89d1621b1 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_method.h @@ -0,0 +1,15 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +- (void)method; +- (void)methodWithInt:(int)foo; +- (void)methodWithFoo:(Foo*)foo; +- (int)methodReturningInt; +- (Foo*)methodReturningFoo; +- (void)methodWithArg1:(int)intvalue andArg2:(char*)ptr andArg3:(float)floatvalue; +- (instancetype)methodWithAndWithoutKeywords:(int)arg1 + arg2Name:(float)arg2 + :(float)arg3 + arg4Name:(int)arg4; +@end diff --git a/bindgen-tests/tests/headers/objc_method_clash.h b/bindgen-tests/tests/headers/objc_method_clash.h new file mode 100644 index 0000000000..d99d3691fe --- /dev/null +++ b/bindgen-tests/tests/headers/objc_method_clash.h @@ -0,0 +1,7 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo ++ (void)foo; +- (void)foo; +@end diff --git a/bindgen-tests/tests/headers/objc_pointer_return_types.h b/bindgen-tests/tests/headers/objc_pointer_return_types.h new file mode 100644 index 0000000000..4d1a6dea34 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_pointer_return_types.h @@ -0,0 +1,10 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Bar +@end + +@interface Foo ++ (Bar*)methodReturningBar; +- (void)methodUsingBar:(Bar *)my_bar; +@end diff --git a/bindgen-tests/tests/headers/objc_property_fnptr.h b/bindgen-tests/tests/headers/objc_property_fnptr.h new file mode 100644 index 0000000000..fe3e7fcc99 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_property_fnptr.h @@ -0,0 +1,6 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo +@property int (*func)(char, short, float); +@end diff --git a/bindgen-tests/tests/headers/objc_protocol.h b/bindgen-tests/tests/headers/objc_protocol.h new file mode 100644 index 0000000000..46978a3b4e --- /dev/null +++ b/bindgen-tests/tests/headers/objc_protocol.h @@ -0,0 +1,8 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@protocol Foo +@end + +@interface Foo +@end diff --git a/bindgen-tests/tests/headers/objc_protocol_inheritance.h b/bindgen-tests/tests/headers/objc_protocol_inheritance.h new file mode 100644 index 0000000000..13135fddbc --- /dev/null +++ b/bindgen-tests/tests/headers/objc_protocol_inheritance.h @@ -0,0 +1,11 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@protocol Foo +@end + +@interface Foo +@end + +@interface Bar : Foo +@end diff --git a/bindgen-tests/tests/headers/objc_sel_and_id.h b/bindgen-tests/tests/headers/objc_sel_and_id.h new file mode 100644 index 0000000000..6491a541c6 --- /dev/null +++ b/bindgen-tests/tests/headers/objc_sel_and_id.h @@ -0,0 +1,7 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +id object; +SEL selector; + +void f(id object, SEL selector); diff --git a/bindgen-tests/tests/headers/objc_template.h b/bindgen-tests/tests/headers/objc_template.h new file mode 100644 index 0000000000..b616da013f --- /dev/null +++ b/bindgen-tests/tests/headers/objc_template.h @@ -0,0 +1,10 @@ +// bindgen-flags: -- -x objective-c +// bindgen-osx-only + +@interface Foo<__covariant ObjectType> +- (ObjectType)get; +@end + +@interface FooMultiGeneric<__covariant KeyType, __covariant ObjectType> +- (nullable ObjectType)objectForKey:(KeyType)key; +@end diff --git a/tests/headers/only_bitfields.hpp b/bindgen-tests/tests/headers/only_bitfields.hpp similarity index 100% rename from tests/headers/only_bitfields.hpp rename to bindgen-tests/tests/headers/only_bitfields.hpp diff --git a/tests/headers/opaque-template-inst-member-2.hpp b/bindgen-tests/tests/headers/opaque-template-inst-member-2.hpp similarity index 100% rename from tests/headers/opaque-template-inst-member-2.hpp rename to bindgen-tests/tests/headers/opaque-template-inst-member-2.hpp diff --git a/tests/headers/opaque-template-inst-member.hpp b/bindgen-tests/tests/headers/opaque-template-inst-member.hpp similarity index 100% rename from tests/headers/opaque-template-inst-member.hpp rename to bindgen-tests/tests/headers/opaque-template-inst-member.hpp diff --git a/tests/headers/opaque-template-instantiation-namespaced.hpp b/bindgen-tests/tests/headers/opaque-template-instantiation-namespaced.hpp similarity index 100% rename from tests/headers/opaque-template-instantiation-namespaced.hpp rename to bindgen-tests/tests/headers/opaque-template-instantiation-namespaced.hpp diff --git a/tests/headers/opaque-template-instantiation.hpp b/bindgen-tests/tests/headers/opaque-template-instantiation.hpp similarity index 100% rename from tests/headers/opaque-template-instantiation.hpp rename to bindgen-tests/tests/headers/opaque-template-instantiation.hpp diff --git a/bindgen-tests/tests/headers/opaque-tracing.hpp b/bindgen-tests/tests/headers/opaque-tracing.hpp new file mode 100644 index 0000000000..cf65276a68 --- /dev/null +++ b/bindgen-tests/tests/headers/opaque-tracing.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --opaque-type ".*" --allowlist-function=foo --with-derive-hash --with-derive-partialeq --with-derive-eq + +class Container; + +// The allowlist tracing should reach the Container type, even though it's +// marked as opaque. +void foo(Container* c); + +template +class Wat { + T foo; +}; + +class OtherOpaque { + int bar; +}; + +class Container { + Wat bar; + OtherOpaque baz; +}; diff --git a/tests/headers/opaque_in_struct.hpp b/bindgen-tests/tests/headers/opaque_in_struct.hpp similarity index 100% rename from tests/headers/opaque_in_struct.hpp rename to bindgen-tests/tests/headers/opaque_in_struct.hpp diff --git a/tests/headers/opaque_pointer.hpp b/bindgen-tests/tests/headers/opaque_pointer.hpp similarity index 100% rename from tests/headers/opaque_pointer.hpp rename to bindgen-tests/tests/headers/opaque_pointer.hpp diff --git a/tests/headers/opaque_typedef.hpp b/bindgen-tests/tests/headers/opaque_typedef.hpp similarity index 100% rename from tests/headers/opaque_typedef.hpp rename to bindgen-tests/tests/headers/opaque_typedef.hpp diff --git a/bindgen-tests/tests/headers/opencl_vector.h b/bindgen-tests/tests/headers/opencl_vector.h new file mode 100644 index 0000000000..79022c768f --- /dev/null +++ b/bindgen-tests/tests/headers/opencl_vector.h @@ -0,0 +1,9 @@ +typedef float float4 __attribute__((ext_vector_type(4))); +typedef float float2 __attribute__((ext_vector_type(2))); + +float4 foo(float2 a, float2 b) { + float4 c; + c.xz = a; + c.yw = b; + return c; +} \ No newline at end of file diff --git a/bindgen-tests/tests/headers/operator.hpp b/bindgen-tests/tests/headers/operator.hpp new file mode 100644 index 0000000000..186f1fe683 --- /dev/null +++ b/bindgen-tests/tests/headers/operator.hpp @@ -0,0 +1,5 @@ +int operator_information(void); + +class Foo; +int operator<<(const Foo&, int); + diff --git a/bindgen-tests/tests/headers/operator_equals.hpp b/bindgen-tests/tests/headers/operator_equals.hpp new file mode 100644 index 0000000000..38a3a092a9 --- /dev/null +++ b/bindgen-tests/tests/headers/operator_equals.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --represent-cxx-operators --generate-inline-functions -- -x c++ +// bindgen-parse-callbacks: operator-rename + +class SomeClass { +public: + bool operator=(const SomeClass& another) { + return false; + } +}; diff --git a/bindgen-tests/tests/headers/ord-enum.h b/bindgen-tests/tests/headers/ord-enum.h new file mode 100644 index 0000000000..b14e77c2f8 --- /dev/null +++ b/bindgen-tests/tests/headers/ord-enum.h @@ -0,0 +1,15 @@ +// bindgen-flags: --rustified-enum ".*" --with-derive-ord + +enum A { + A0 = 0, + A1 = 1, + A2 = 2, + A3 = A0 - 1, +}; + +enum B { + B0 = 1, + B1 = B0 + 3, + B2 = B0 + 2, + B3 = B0 - 2, +}; diff --git a/bindgen-tests/tests/headers/overflowed_enum.hpp b/bindgen-tests/tests/headers/overflowed_enum.hpp new file mode 100644 index 0000000000..18d3fe4173 --- /dev/null +++ b/bindgen-tests/tests/headers/overflowed_enum.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 -Wno-narrowing + +enum Foo { + BAP_ARM = 0x93fcb9, + BAP_X86 = 0xb67eed, + BAP_X86_64 = 0xba7b274f, +}; + +enum Bar: unsigned short { + One = 1, + Big = 65538, +}; diff --git a/tests/headers/overloading.hpp b/bindgen-tests/tests/headers/overloading.hpp similarity index 100% rename from tests/headers/overloading.hpp rename to bindgen-tests/tests/headers/overloading.hpp diff --git a/bindgen-tests/tests/headers/packed-bitfield.h b/bindgen-tests/tests/headers/packed-bitfield.h new file mode 100644 index 0000000000..ef23bc6ad2 --- /dev/null +++ b/bindgen-tests/tests/headers/packed-bitfield.h @@ -0,0 +1,5 @@ +struct Date { + unsigned char day: 5; + unsigned char month: 4; + signed short year: 15; +} __attribute__((packed)); diff --git a/bindgen-tests/tests/headers/packed-n-with-padding.h b/bindgen-tests/tests/headers/packed-n-with-padding.h new file mode 100644 index 0000000000..8a6233b52b --- /dev/null +++ b/bindgen-tests/tests/headers/packed-n-with-padding.h @@ -0,0 +1,8 @@ +#pragma pack(push, 2) +struct Packed { + char a; + short b; + char c; + int d; +}; +#pragma pack(pop) diff --git a/bindgen-tests/tests/headers/packed-vtable.h b/bindgen-tests/tests/headers/packed-vtable.h new file mode 100644 index 0000000000..b3405977b5 --- /dev/null +++ b/bindgen-tests/tests/headers/packed-vtable.h @@ -0,0 +1,10 @@ +// bindgen-flags: --raw-line '#![cfg(feature = "nightly")]' -- -x c++ -std=c++11 + +#pragma pack(1) + +// This should be packed. +struct PackedVtable { + virtual ~PackedVtable(); +}; + +#pragma pack() diff --git a/bindgen-tests/tests/headers/parm-union.hpp b/bindgen-tests/tests/headers/parm-union.hpp new file mode 100644 index 0000000000..e36df69120 --- /dev/null +++ b/bindgen-tests/tests/headers/parm-union.hpp @@ -0,0 +1,4 @@ +struct Struct +{ + void Function(union Union&); +}; diff --git a/bindgen-tests/tests/headers/parsecb-anonymous-enum-variant-rename.h b/bindgen-tests/tests/headers/parsecb-anonymous-enum-variant-rename.h new file mode 100644 index 0000000000..9336cf8993 --- /dev/null +++ b/bindgen-tests/tests/headers/parsecb-anonymous-enum-variant-rename.h @@ -0,0 +1,6 @@ +// bindgen-flags: --allowlist-var ^MyVal$ +// bindgen-parse-callbacks: enum-variant-rename + +enum { + MyVal = 0, +}; diff --git a/tests/headers/partial-specialization-and-inheritance.hpp b/bindgen-tests/tests/headers/partial-specialization-and-inheritance.hpp similarity index 100% rename from tests/headers/partial-specialization-and-inheritance.hpp rename to bindgen-tests/tests/headers/partial-specialization-and-inheritance.hpp diff --git a/bindgen-tests/tests/headers/pointer-attr.h b/bindgen-tests/tests/headers/pointer-attr.h new file mode 100644 index 0000000000..fe0004b8bf --- /dev/null +++ b/bindgen-tests/tests/headers/pointer-attr.h @@ -0,0 +1 @@ +void a(const char __attribute__((btf_type_tag("a"))) *); diff --git a/bindgen-tests/tests/headers/prefix-link-name-c.h b/bindgen-tests/tests/headers/prefix-link-name-c.h new file mode 100644 index 0000000000..2432798fce --- /dev/null +++ b/bindgen-tests/tests/headers/prefix-link-name-c.h @@ -0,0 +1,4 @@ +// bindgen-parse-callbacks: prefix-link-name-foo_ +// bindgen-flags: --prefix-link-name foo_ + +int bar(void); diff --git a/bindgen-tests/tests/headers/prefix-link-name-cpp.hpp b/bindgen-tests/tests/headers/prefix-link-name-cpp.hpp new file mode 100644 index 0000000000..4fd2612327 --- /dev/null +++ b/bindgen-tests/tests/headers/prefix-link-name-cpp.hpp @@ -0,0 +1,8 @@ +// bindgen-parse-callbacks: prefix-link-name-foo_ +// bindgen-flags: --prefix-link-name foo_ + +namespace baz { + +int foo(); + +} // end namespace baz diff --git a/bindgen-tests/tests/headers/prepend-enum-constified-variant.h b/bindgen-tests/tests/headers/prepend-enum-constified-variant.h new file mode 100644 index 0000000000..e9ba0e732b --- /dev/null +++ b/bindgen-tests/tests/headers/prepend-enum-constified-variant.h @@ -0,0 +1,6 @@ +// bindgen-flags: --no-prepend-enum-name --rustified-enum ".*" + +enum AVCodecID { + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, + AV_CODEC_ID_TTF = 0x18000, +}; diff --git a/tests/headers/prepend_enum_name.hpp b/bindgen-tests/tests/headers/prepend_enum_name.hpp similarity index 100% rename from tests/headers/prepend_enum_name.hpp rename to bindgen-tests/tests/headers/prepend_enum_name.hpp diff --git a/tests/headers/private.hpp b/bindgen-tests/tests/headers/private.hpp similarity index 100% rename from tests/headers/private.hpp rename to bindgen-tests/tests/headers/private.hpp diff --git a/bindgen-tests/tests/headers/private_fields.hpp b/bindgen-tests/tests/headers/private_fields.hpp new file mode 100644 index 0000000000..965acde9e8 --- /dev/null +++ b/bindgen-tests/tests/headers/private_fields.hpp @@ -0,0 +1,63 @@ +// bindgen-flags: --respect-cxx-access-specs +// bindgen-parse-callbacks: field-visibility-default-public + +class PubPriv { + public: + int x; + private: + int y; +}; + +class PrivateBitFields { + unsigned int a : 4; + unsigned int b : 4; +}; +class PublicBitFields { + public: + unsigned int a : 4; + unsigned int b : 4; +}; +class MixedBitFields { + unsigned int a : 4; + public: + unsigned int d : 4; +}; + +class Base { + public: + int member; +}; + +class InheritsPrivately : Base {}; +class InheritsPublically : public Base {}; + +class WithAnonStruct { + struct { + int a; + }; + public: + struct { + int b; + }; +}; + +class WithAnonUnion { + union {}; +}; + +class Override { + public: + unsigned int a; + // override with annotation + /**
*/ + unsigned int b; + // override with callback + unsigned int private_c; + + unsigned int bf_a : 4; + // override with annotation + /**
*/ + unsigned int bf_b : 4; + // override with callback + unsigned int private_bf_c : 4; +}; diff --git a/bindgen-tests/tests/headers/ptr32-has-different-size.h b/bindgen-tests/tests/headers/ptr32-has-different-size.h new file mode 100644 index 0000000000..8cda702c53 --- /dev/null +++ b/bindgen-tests/tests/headers/ptr32-has-different-size.h @@ -0,0 +1,4 @@ +// bindgen-flags: -- -fms-extensions +typedef struct TEST_STRUCT { + void* __ptr32 ptr_32bit; +} TEST; diff --git a/bindgen-tests/tests/headers/public-dtor.hpp b/bindgen-tests/tests/headers/public-dtor.hpp new file mode 100644 index 0000000000..60d69d799f --- /dev/null +++ b/bindgen-tests/tests/headers/public-dtor.hpp @@ -0,0 +1,18 @@ + +namespace cv { + class Foo { + public: + ~Foo(); + }; + + Foo::~Foo() {} + + class Bar { + public: + ~Bar(); + }; + + inline + Bar::~Bar() {} + +} diff --git a/bindgen-tests/tests/headers/qualified-dependent-types.hpp b/bindgen-tests/tests/headers/qualified-dependent-types.hpp new file mode 100644 index 0000000000..fcdfc87c81 --- /dev/null +++ b/bindgen-tests/tests/headers/qualified-dependent-types.hpp @@ -0,0 +1,16 @@ +// Issue #2085. + +template +struct Foo; + +template +struct Bar {}; + +template +struct Bar { + using BarDependent = typename Foo::Dependent; + void method(const BarDependent &); +}; + +template +void Bar::method(const BarDependent &) {} diff --git a/tests/headers/redeclaration.hpp b/bindgen-tests/tests/headers/redeclaration.hpp similarity index 100% rename from tests/headers/redeclaration.hpp rename to bindgen-tests/tests/headers/redeclaration.hpp diff --git a/bindgen-tests/tests/headers/redundant-packed-and-align.h b/bindgen-tests/tests/headers/redundant-packed-and-align.h new file mode 100644 index 0000000000..75e15e4139 --- /dev/null +++ b/bindgen-tests/tests/headers/redundant-packed-and-align.h @@ -0,0 +1,42 @@ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +struct redundant_packed { + uint32_t a; + uint32_t b; +} __attribute__((packed, aligned(8))); + +struct redundant_packed_bitfield { + uint8_t a[3]; + uint8_t b0:1; + uint8_t b1:1; + uint32_t c; +} __attribute__((packed, aligned(8))); + + +union redundant_packed_union { + uint64_t a; + uint32_t b; +} __attribute__((packed, aligned(16))); + + +struct inner { + uint8_t a; +} __attribute__((packed, aligned(2))); + +struct outer_redundant_packed { + struct inner a[2]; + uint32_t b; +} __attribute__((packed, aligned(8))); + + +#pragma pack(2) + +struct redundant_pragma_packed { + uint8_t a; + uint16_t b; +} __attribute__((aligned(4))); + +#pragma pack() diff --git a/tests/headers/ref_argument_array.hpp b/bindgen-tests/tests/headers/ref_argument_array.hpp similarity index 100% rename from tests/headers/ref_argument_array.hpp rename to bindgen-tests/tests/headers/ref_argument_array.hpp diff --git a/bindgen-tests/tests/headers/references.hpp b/bindgen-tests/tests/headers/references.hpp new file mode 100644 index 0000000000..6b56823d12 --- /dev/null +++ b/bindgen-tests/tests/headers/references.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --nonnull-references + +struct Container { + int *normalPointer; + const int *constPointer; + int &normalRef; + const int &constRef; + int *&pointerRef; + const int *&constPointerRef; +}; + +int &refReturningFunction(); + +void functionConsumingRef(int &someRef, float normalArgument, + const int &constRef); + +void functionConsumingPointerRef(int* &pointerRef); diff --git a/tests/headers/reparented_replacement.hpp b/bindgen-tests/tests/headers/reparented_replacement.hpp similarity index 100% rename from tests/headers/reparented_replacement.hpp rename to bindgen-tests/tests/headers/reparented_replacement.hpp diff --git a/tests/headers/replace_template_alias.hpp b/bindgen-tests/tests/headers/replace_template_alias.hpp similarity index 100% rename from tests/headers/replace_template_alias.hpp rename to bindgen-tests/tests/headers/replace_template_alias.hpp diff --git a/tests/headers/replace_use.hpp b/bindgen-tests/tests/headers/replace_use.hpp similarity index 100% rename from tests/headers/replace_use.hpp rename to bindgen-tests/tests/headers/replace_use.hpp diff --git a/tests/headers/replaces_double.hpp b/bindgen-tests/tests/headers/replaces_double.hpp similarity index 85% rename from tests/headers/replaces_double.hpp rename to bindgen-tests/tests/headers/replaces_double.hpp index 1a78b0d92b..ce6a8dbb45 100644 --- a/tests/headers/replaces_double.hpp +++ b/bindgen-tests/tests/headers/replaces_double.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --blacklist-type Wrapper -- --std=c++11 +// bindgen-flags: --blocklist-type Wrapper -- --std=c++11 template struct Wrapper { diff --git a/bindgen-tests/tests/headers/repr-align.hpp b/bindgen-tests/tests/headers/repr-align.hpp new file mode 100644 index 0000000000..a7719e10ed --- /dev/null +++ b/bindgen-tests/tests/headers/repr-align.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --raw-line '#![cfg(feature = "nightly")]' -- -std=c++11 + +struct alignas(8) a { + int b; + int c; +}; + +struct alignas(double) b { + int b; + int c; +}; diff --git a/tests/headers/resolved_type_def_function.h b/bindgen-tests/tests/headers/resolved_type_def_function.h similarity index 100% rename from tests/headers/resolved_type_def_function.h rename to bindgen-tests/tests/headers/resolved_type_def_function.h diff --git a/tests/headers/same_struct_name_in_different_namespaces.hpp b/bindgen-tests/tests/headers/same_struct_name_in_different_namespaces.hpp similarity index 100% rename from tests/headers/same_struct_name_in_different_namespaces.hpp rename to bindgen-tests/tests/headers/same_struct_name_in_different_namespaces.hpp diff --git a/tests/headers/sentry-defined-multiple-times.hpp b/bindgen-tests/tests/headers/sentry-defined-multiple-times.hpp similarity index 100% rename from tests/headers/sentry-defined-multiple-times.hpp rename to bindgen-tests/tests/headers/sentry-defined-multiple-times.hpp diff --git a/tests/headers/short-enums.hpp b/bindgen-tests/tests/headers/short-enums.hpp similarity index 83% rename from tests/headers/short-enums.hpp rename to bindgen-tests/tests/headers/short-enums.hpp index 0b517d6f7b..14f833de64 100644 --- a/tests/headers/short-enums.hpp +++ b/bindgen-tests/tests/headers/short-enums.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 -fshort-enums +// bindgen-flags: --rustified-enum ".*" -- -std=c++11 -fshort-enums typedef enum { SOME_VALUE = 0x1, diff --git a/tests/headers/size_t_template.hpp b/bindgen-tests/tests/headers/size_t_template.hpp similarity index 100% rename from tests/headers/size_t_template.hpp rename to bindgen-tests/tests/headers/size_t_template.hpp diff --git a/bindgen-tests/tests/headers/sorted_items.hpp b/bindgen-tests/tests/headers/sorted_items.hpp new file mode 100644 index 0000000000..9b5ced9637 --- /dev/null +++ b/bindgen-tests/tests/headers/sorted_items.hpp @@ -0,0 +1,35 @@ +// bindgen-flags: --sort-semantically --enable-cxx-namespaces -- --target=x86_64-unknown-linux + +int foo(); +typedef int number; +int bar(number x); +struct Point +{ + number x; + number y; +}; +struct Angle +{ + number a; + number b; +}; +int baz(struct Point point); +const number NUMBER = 42; + +namespace ns { + int foo(); + typedef int number; + int bar(number x); + struct Point + { + number x; + number y; + }; + struct Angle + { + number a; + number b; + }; + int baz(struct Point point); + const number NUMBER = 42; +} diff --git a/bindgen-tests/tests/headers/special-members.hpp b/bindgen-tests/tests/headers/special-members.hpp new file mode 100644 index 0000000000..753b2fdc0a --- /dev/null +++ b/bindgen-tests/tests/headers/special-members.hpp @@ -0,0 +1,7 @@ +class A { +public: + A(); + A(A&); + A(A&&); + ~A(); +}; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/specific_receiver.hpp b/bindgen-tests/tests/headers/specific_receiver.hpp new file mode 100644 index 0000000000..a521f9f0b2 --- /dev/null +++ b/bindgen-tests/tests/headers/specific_receiver.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --use-specific-virtual-function-receiver --generate-inline-functions -- -x c++ -std=c++14 + +class Fish { +public: + virtual void swim() { + } +}; diff --git a/bindgen-tests/tests/headers/stdint_typedef.h b/bindgen-tests/tests/headers/stdint_typedef.h new file mode 100644 index 0000000000..f716a7f1a0 --- /dev/null +++ b/bindgen-tests/tests/headers/stdint_typedef.h @@ -0,0 +1,10 @@ +// bindgen-flags: --allowlist-type="Struct" --allowlist-function="fun" + +// no typedef should be emitted for `__uint64_t` +typedef unsigned long long __uint64_t; +typedef __uint64_t uint64_t; + +uint64_t fun(); +struct Struct { + uint64_t field; +}; diff --git a/bindgen-tests/tests/headers/strings_array.h b/bindgen-tests/tests/headers/strings_array.h new file mode 100644 index 0000000000..fa7bf561fa --- /dev/null +++ b/bindgen-tests/tests/headers/strings_array.h @@ -0,0 +1,3 @@ +const char* MY_STRING_UTF8 = "Hello, world!"; +const char* MY_STRING_INTERIOR_NULL = "Hello,\0World!"; +const char* MY_STRING_NON_UTF8 = "ABCDE\xFF"; diff --git a/bindgen-tests/tests/headers/strings_cstr.h b/bindgen-tests/tests/headers/strings_cstr.h new file mode 100644 index 0000000000..8b1d40e689 --- /dev/null +++ b/bindgen-tests/tests/headers/strings_cstr.h @@ -0,0 +1,5 @@ +// bindgen-flags: --rust-target=1.59 --generate-cstr + +const char* MY_STRING_UTF8 = "Hello, world!"; +const char* MY_STRING_INTERIOR_NULL = "Hello,\0World!"; +const char* MY_STRING_NON_UTF8 = "ABCDE\xFF"; diff --git a/bindgen-tests/tests/headers/strings_cstr2.h b/bindgen-tests/tests/headers/strings_cstr2.h new file mode 100644 index 0000000000..2cd7e6222d --- /dev/null +++ b/bindgen-tests/tests/headers/strings_cstr2.h @@ -0,0 +1,5 @@ +// bindgen-flags: --rust-target=1.77 --generate-cstr + +const char* MY_STRING_UTF8 = "Hello, world!"; +const char* MY_STRING_INTERIOR_NULL = "Hello,\0World!"; +const char* MY_STRING_NON_UTF8 = "ABCDE\xFF"; diff --git a/bindgen-tests/tests/headers/strings_cstr2_2018.h b/bindgen-tests/tests/headers/strings_cstr2_2018.h new file mode 100644 index 0000000000..67d117a1bc --- /dev/null +++ b/bindgen-tests/tests/headers/strings_cstr2_2018.h @@ -0,0 +1,5 @@ +// bindgen-flags: --rust-target=1.77 --rust-edition=2018 --generate-cstr + +const char* MY_STRING_UTF8 = "Hello, world!"; +const char* MY_STRING_INTERIOR_NULL = "Hello,\0World!"; +const char* MY_STRING_NON_UTF8 = "ABCDE\xFF"; diff --git a/tests/headers/struct_containing_forward_declared_struct.h b/bindgen-tests/tests/headers/struct_containing_forward_declared_struct.h similarity index 100% rename from tests/headers/struct_containing_forward_declared_struct.h rename to bindgen-tests/tests/headers/struct_containing_forward_declared_struct.h diff --git a/tests/headers/struct_typedef.h b/bindgen-tests/tests/headers/struct_typedef.h similarity index 90% rename from tests/headers/struct_typedef.h rename to bindgen-tests/tests/headers/struct_typedef.h index e996b28f0f..2ed7aabd94 100644 --- a/tests/headers/struct_typedef.h +++ b/bindgen-tests/tests/headers/struct_typedef.h @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" // typedef struct { _Bool has_name; diff --git a/tests/headers/struct_typedef_ns.hpp b/bindgen-tests/tests/headers/struct_typedef_ns.hpp similarity index 84% rename from tests/headers/struct_typedef_ns.hpp rename to bindgen-tests/tests/headers/struct_typedef_ns.hpp index a5a8f9a64e..40a7c680a2 100644 --- a/tests/headers/struct_typedef_ns.hpp +++ b/bindgen-tests/tests/headers/struct_typedef_ns.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --enable-cxx-namespaces --rustified-enum .* +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --enable-cxx-namespaces --rustified-enum ".*" namespace whatever { typedef struct { diff --git a/tests/headers/struct_with_anon_struct.h b/bindgen-tests/tests/headers/struct_with_anon_struct.h similarity index 100% rename from tests/headers/struct_with_anon_struct.h rename to bindgen-tests/tests/headers/struct_with_anon_struct.h diff --git a/tests/headers/struct_with_anon_struct_array.h b/bindgen-tests/tests/headers/struct_with_anon_struct_array.h similarity index 100% rename from tests/headers/struct_with_anon_struct_array.h rename to bindgen-tests/tests/headers/struct_with_anon_struct_array.h diff --git a/tests/headers/struct_with_anon_struct_pointer.h b/bindgen-tests/tests/headers/struct_with_anon_struct_pointer.h similarity index 100% rename from tests/headers/struct_with_anon_struct_pointer.h rename to bindgen-tests/tests/headers/struct_with_anon_struct_pointer.h diff --git a/tests/headers/struct_with_anon_union.h b/bindgen-tests/tests/headers/struct_with_anon_union.h similarity index 100% rename from tests/headers/struct_with_anon_union.h rename to bindgen-tests/tests/headers/struct_with_anon_union.h diff --git a/tests/headers/struct_with_anon_unnamed_struct.h b/bindgen-tests/tests/headers/struct_with_anon_unnamed_struct.h similarity index 100% rename from tests/headers/struct_with_anon_unnamed_struct.h rename to bindgen-tests/tests/headers/struct_with_anon_unnamed_struct.h diff --git a/tests/headers/struct_with_anon_unnamed_union.h b/bindgen-tests/tests/headers/struct_with_anon_unnamed_union.h similarity index 100% rename from tests/headers/struct_with_anon_unnamed_union.h rename to bindgen-tests/tests/headers/struct_with_anon_unnamed_union.h diff --git a/tests/headers/struct_with_bitfields.h b/bindgen-tests/tests/headers/struct_with_bitfields.h similarity index 100% rename from tests/headers/struct_with_bitfields.h rename to bindgen-tests/tests/headers/struct_with_bitfields.h diff --git a/tests/headers/struct_with_derive_debug.h b/bindgen-tests/tests/headers/struct_with_derive_debug.h similarity index 100% rename from tests/headers/struct_with_derive_debug.h rename to bindgen-tests/tests/headers/struct_with_derive_debug.h diff --git a/bindgen-tests/tests/headers/struct_with_large_array.hpp b/bindgen-tests/tests/headers/struct_with_large_array.hpp new file mode 100644 index 0000000000..58e8e4d19a --- /dev/null +++ b/bindgen-tests/tests/headers/struct_with_large_array.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq +// +struct S { + char large_array[33]; +}; + +template struct ST { + T large_array[33]; +}; diff --git a/tests/headers/struct_with_nesting.h b/bindgen-tests/tests/headers/struct_with_nesting.h similarity index 100% rename from tests/headers/struct_with_nesting.h rename to bindgen-tests/tests/headers/struct_with_nesting.h diff --git a/tests/headers/struct_with_packing.h b/bindgen-tests/tests/headers/struct_with_packing.h similarity index 100% rename from tests/headers/struct_with_packing.h rename to bindgen-tests/tests/headers/struct_with_packing.h diff --git a/tests/headers/struct_with_struct.h b/bindgen-tests/tests/headers/struct_with_struct.h similarity index 100% rename from tests/headers/struct_with_struct.h rename to bindgen-tests/tests/headers/struct_with_struct.h diff --git a/tests/headers/struct_with_typedef_template_arg.hpp b/bindgen-tests/tests/headers/struct_with_typedef_template_arg.hpp similarity index 100% rename from tests/headers/struct_with_typedef_template_arg.hpp rename to bindgen-tests/tests/headers/struct_with_typedef_template_arg.hpp diff --git a/tests/headers/template-fun-ty.hpp b/bindgen-tests/tests/headers/template-fun-ty.hpp similarity index 100% rename from tests/headers/template-fun-ty.hpp rename to bindgen-tests/tests/headers/template-fun-ty.hpp diff --git a/tests/headers/template-param-usage-0.hpp b/bindgen-tests/tests/headers/template-param-usage-0.hpp similarity index 100% rename from tests/headers/template-param-usage-0.hpp rename to bindgen-tests/tests/headers/template-param-usage-0.hpp diff --git a/tests/headers/template-param-usage-1.hpp b/bindgen-tests/tests/headers/template-param-usage-1.hpp similarity index 100% rename from tests/headers/template-param-usage-1.hpp rename to bindgen-tests/tests/headers/template-param-usage-1.hpp diff --git a/tests/headers/template-param-usage-10.hpp b/bindgen-tests/tests/headers/template-param-usage-10.hpp similarity index 100% rename from tests/headers/template-param-usage-10.hpp rename to bindgen-tests/tests/headers/template-param-usage-10.hpp diff --git a/tests/headers/template-param-usage-11.hpp b/bindgen-tests/tests/headers/template-param-usage-11.hpp similarity index 100% rename from tests/headers/template-param-usage-11.hpp rename to bindgen-tests/tests/headers/template-param-usage-11.hpp diff --git a/tests/headers/template-param-usage-12.hpp b/bindgen-tests/tests/headers/template-param-usage-12.hpp similarity index 100% rename from tests/headers/template-param-usage-12.hpp rename to bindgen-tests/tests/headers/template-param-usage-12.hpp diff --git a/tests/headers/template-param-usage-13.hpp b/bindgen-tests/tests/headers/template-param-usage-13.hpp similarity index 100% rename from tests/headers/template-param-usage-13.hpp rename to bindgen-tests/tests/headers/template-param-usage-13.hpp diff --git a/tests/headers/template-param-usage-14.hpp b/bindgen-tests/tests/headers/template-param-usage-14.hpp similarity index 100% rename from tests/headers/template-param-usage-14.hpp rename to bindgen-tests/tests/headers/template-param-usage-14.hpp diff --git a/tests/headers/template-param-usage-15.hpp b/bindgen-tests/tests/headers/template-param-usage-15.hpp similarity index 100% rename from tests/headers/template-param-usage-15.hpp rename to bindgen-tests/tests/headers/template-param-usage-15.hpp diff --git a/tests/headers/template-param-usage-2.hpp b/bindgen-tests/tests/headers/template-param-usage-2.hpp similarity index 100% rename from tests/headers/template-param-usage-2.hpp rename to bindgen-tests/tests/headers/template-param-usage-2.hpp diff --git a/tests/headers/template-param-usage-3.hpp b/bindgen-tests/tests/headers/template-param-usage-3.hpp similarity index 100% rename from tests/headers/template-param-usage-3.hpp rename to bindgen-tests/tests/headers/template-param-usage-3.hpp diff --git a/tests/headers/template-param-usage-4.hpp b/bindgen-tests/tests/headers/template-param-usage-4.hpp similarity index 100% rename from tests/headers/template-param-usage-4.hpp rename to bindgen-tests/tests/headers/template-param-usage-4.hpp diff --git a/tests/headers/template-param-usage-5.hpp b/bindgen-tests/tests/headers/template-param-usage-5.hpp similarity index 100% rename from tests/headers/template-param-usage-5.hpp rename to bindgen-tests/tests/headers/template-param-usage-5.hpp diff --git a/tests/headers/template-param-usage-6.hpp b/bindgen-tests/tests/headers/template-param-usage-6.hpp similarity index 100% rename from tests/headers/template-param-usage-6.hpp rename to bindgen-tests/tests/headers/template-param-usage-6.hpp diff --git a/tests/headers/template-param-usage-7.hpp b/bindgen-tests/tests/headers/template-param-usage-7.hpp similarity index 76% rename from tests/headers/template-param-usage-7.hpp rename to bindgen-tests/tests/headers/template-param-usage-7.hpp index 99d4cc71b4..3d70cee145 100644 --- a/tests/headers/template-param-usage-7.hpp +++ b/bindgen-tests/tests/headers/template-param-usage-7.hpp @@ -6,5 +6,5 @@ class DoesNotUseU { V v; }; -// The bool should go away becuase U is not used. +// The bool should go away because U is not used. using Alias = DoesNotUseU; diff --git a/tests/headers/template-param-usage-8.hpp b/bindgen-tests/tests/headers/template-param-usage-8.hpp similarity index 100% rename from tests/headers/template-param-usage-8.hpp rename to bindgen-tests/tests/headers/template-param-usage-8.hpp diff --git a/tests/headers/template-param-usage-9.hpp b/bindgen-tests/tests/headers/template-param-usage-9.hpp similarity index 100% rename from tests/headers/template-param-usage-9.hpp rename to bindgen-tests/tests/headers/template-param-usage-9.hpp diff --git a/tests/headers/template-with-var.hpp b/bindgen-tests/tests/headers/template-with-var.hpp similarity index 100% rename from tests/headers/template-with-var.hpp rename to bindgen-tests/tests/headers/template-with-var.hpp diff --git a/tests/headers/template.hpp b/bindgen-tests/tests/headers/template.hpp similarity index 95% rename from tests/headers/template.hpp rename to bindgen-tests/tests/headers/template.hpp index eea2c4def5..bc32a357e8 100644 --- a/tests/headers/template.hpp +++ b/bindgen-tests/tests/headers/template.hpp @@ -32,9 +32,7 @@ struct C { B mBConstRef; B mPtrRef; B mArrayRef; - // clang 3.x ignores const in this case, so they generate different - // result than clang 4.0. - // B mBConstArray; + B mBConstArray; }; template diff --git a/tests/headers/template_alias.hpp b/bindgen-tests/tests/headers/template_alias.hpp similarity index 100% rename from tests/headers/template_alias.hpp rename to bindgen-tests/tests/headers/template_alias.hpp diff --git a/tests/headers/template_alias_basic.hpp b/bindgen-tests/tests/headers/template_alias_basic.hpp similarity index 100% rename from tests/headers/template_alias_basic.hpp rename to bindgen-tests/tests/headers/template_alias_basic.hpp diff --git a/tests/headers/template_alias_namespace.hpp b/bindgen-tests/tests/headers/template_alias_namespace.hpp similarity index 100% rename from tests/headers/template_alias_namespace.hpp rename to bindgen-tests/tests/headers/template_alias_namespace.hpp diff --git a/bindgen-tests/tests/headers/template_fun.hpp b/bindgen-tests/tests/headers/template_fun.hpp new file mode 100644 index 0000000000..17b1383bcf --- /dev/null +++ b/bindgen-tests/tests/headers/template_fun.hpp @@ -0,0 +1,3 @@ +// this will be ignored +template +void foo() {} diff --git a/bindgen-tests/tests/headers/template_instantiation_with_fn_local_type.hpp b/bindgen-tests/tests/headers/template_instantiation_with_fn_local_type.hpp new file mode 100644 index 0000000000..b7ff28b099 --- /dev/null +++ b/bindgen-tests/tests/headers/template_instantiation_with_fn_local_type.hpp @@ -0,0 +1,27 @@ +// bindgen-flags: -- -std=c++14 +// +// https://github.com/rust-lang/rust-bindgen/issues/2036 + +template +struct Foo {}; +template +Foo foo{}; + +// Struct inside function +void f() { + struct Bar { + Bar() {} + }; + foo; +} + +// Struct inside method +class Baz { + void f() { + struct Boo { + Boo() {} + }; + foo; + } +}; + diff --git a/tests/headers/template_partial_specification.hpp b/bindgen-tests/tests/headers/template_partial_specification.hpp similarity index 100% rename from tests/headers/template_partial_specification.hpp rename to bindgen-tests/tests/headers/template_partial_specification.hpp diff --git a/tests/headers/template_typedef_transitive_param.hpp b/bindgen-tests/tests/headers/template_typedef_transitive_param.hpp similarity index 100% rename from tests/headers/template_typedef_transitive_param.hpp rename to bindgen-tests/tests/headers/template_typedef_transitive_param.hpp diff --git a/tests/headers/template_typedefs.hpp b/bindgen-tests/tests/headers/template_typedefs.hpp similarity index 100% rename from tests/headers/template_typedefs.hpp rename to bindgen-tests/tests/headers/template_typedefs.hpp diff --git a/tests/headers/templateref_opaque.hpp b/bindgen-tests/tests/headers/templateref_opaque.hpp similarity index 100% rename from tests/headers/templateref_opaque.hpp rename to bindgen-tests/tests/headers/templateref_opaque.hpp diff --git a/tests/headers/templatized-bitfield.hpp b/bindgen-tests/tests/headers/templatized-bitfield.hpp similarity index 100% rename from tests/headers/templatized-bitfield.hpp rename to bindgen-tests/tests/headers/templatized-bitfield.hpp diff --git a/bindgen-tests/tests/headers/timex.h b/bindgen-tests/tests/headers/timex.h new file mode 100644 index 0000000000..1add26cabe --- /dev/null +++ b/bindgen-tests/tests/headers/timex.h @@ -0,0 +1,15 @@ +struct timex { + int tai; + + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; +}; + +struct timex_named { + int tai; + + int a:32; int b:32; int c:32; int d:32; + int e:32; int f:32; int g:32; int h:32; + int i:32; int j:32; int k:32; +}; diff --git a/bindgen-tests/tests/headers/transform-op.hpp b/bindgen-tests/tests/headers/transform-op.hpp new file mode 100644 index 0000000000..090e88b34b --- /dev/null +++ b/bindgen-tests/tests/headers/transform-op.hpp @@ -0,0 +1,75 @@ +// bindgen-flags: -- -std=c++11 + +typedef unsigned char uint8_t; +typedef int int32_t; + +template +struct StylePoint { + T x; + T y; +}; + +template +union StyleFoo { + enum class Tag : uint8_t { + Foo, + Bar, + Baz, + Bazz, + }; + + struct Foo_Body { + Tag tag; + int32_t x; + StylePoint y; + StylePoint z; + }; + + struct Bar_Body { + Tag tag; + T _0; + }; + + struct Baz_Body { + Tag tag; + StylePoint _0; + }; + + struct { + Tag tag; + }; + Foo_Body foo; + Bar_Body bar; + Baz_Body baz; +}; + +template +struct StyleBar { + enum class Tag { + Bar1, + Bar2, + Bar3, + Bar4, + }; + + struct StyleBar1_Body { + int32_t x; + StylePoint y; + StylePoint z; + }; + + struct StyleBar2_Body { + T _0; + }; + + struct StyleBar3_Body { + StylePoint _0; + }; + + Tag tag; + union { + StyleBar1_Body bar1; + StyleBar2_Body bar2; + StyleBar3_Body bar3; + }; +}; diff --git a/bindgen-tests/tests/headers/type-referenced-by-allowlisted-function.h b/bindgen-tests/tests/headers/type-referenced-by-allowlisted-function.h new file mode 100644 index 0000000000..bf675bc9a7 --- /dev/null +++ b/bindgen-tests/tests/headers/type-referenced-by-allowlisted-function.h @@ -0,0 +1,7 @@ +// bindgen-flags: --allowlist-function dl_iterate_phdr + +struct dl_phdr_info { + int x; +}; + +int dl_iterate_phdr(struct dl_phdr_info *); diff --git a/bindgen-tests/tests/headers/type_alias_empty.hpp b/bindgen-tests/tests/headers/type_alias_empty.hpp new file mode 100644 index 0000000000..bcccc3c85e --- /dev/null +++ b/bindgen-tests/tests/headers/type_alias_empty.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --allowlist-type bool_constant -- -std=c++11 + +// NB: The --allowlist-type is done to trigger the traversal of the types on +// codegen in order to trigger #67. + +template +struct integral_constant {}; + +template +using bool_constant = integral_constant; diff --git a/tests/headers/type_alias_partial_template_especialization.hpp b/bindgen-tests/tests/headers/type_alias_partial_template_especialization.hpp similarity index 100% rename from tests/headers/type_alias_partial_template_especialization.hpp rename to bindgen-tests/tests/headers/type_alias_partial_template_especialization.hpp diff --git a/tests/headers/type_alias_template_specialized.hpp b/bindgen-tests/tests/headers/type_alias_template_specialized.hpp similarity index 77% rename from tests/headers/type_alias_template_specialized.hpp rename to bindgen-tests/tests/headers/type_alias_template_specialized.hpp index a2d32b56a1..f7403a36d0 100644 --- a/tests/headers/type_alias_template_specialized.hpp +++ b/bindgen-tests/tests/headers/type_alias_template_specialized.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --whitelist-type Rooted -- -std=c++14 +// bindgen-flags: --allowlist-type Rooted -- -std=c++14 template using MaybeWrapped = a; class Rooted { diff --git a/bindgen-tests/tests/headers/typedef-pointer-overlap.h b/bindgen-tests/tests/headers/typedef-pointer-overlap.h new file mode 100644 index 0000000000..8c556c9b38 --- /dev/null +++ b/bindgen-tests/tests/headers/typedef-pointer-overlap.h @@ -0,0 +1,30 @@ +typedef const struct foo { + char inner; +} *foo; + +typedef struct bar { + char inner; +} *bar; + +typedef struct baz *baz; + +typedef union cat { + int standard_issue; +} *cat; + +typedef enum mad { scientist } *mad; + +void takes_foo_ptr(foo); +void takes_foo_struct(struct foo); + +void takes_bar_ptr(bar); +void takes_bar_struct(struct bar); + +void takes_baz_ptr(baz); +void takes_baz_struct(struct baz); + +void takes_cat_ptr(cat); +void takes_cat_union(union cat); + +void takes_mad_ptr(mad); +void takes_mad_enum(enum mad); diff --git a/tests/headers/typedefd-array-as-function-arg.h b/bindgen-tests/tests/headers/typedefd-array-as-function-arg.h similarity index 100% rename from tests/headers/typedefd-array-as-function-arg.h rename to bindgen-tests/tests/headers/typedefd-array-as-function-arg.h diff --git a/tests/headers/typeref.hpp b/bindgen-tests/tests/headers/typeref.hpp similarity index 100% rename from tests/headers/typeref.hpp rename to bindgen-tests/tests/headers/typeref.hpp diff --git a/bindgen-tests/tests/headers/uncallable_functions.hpp b/bindgen-tests/tests/headers/uncallable_functions.hpp new file mode 100644 index 0000000000..9187470c65 --- /dev/null +++ b/bindgen-tests/tests/headers/uncallable_functions.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --generate-deleted-functions --generate-private-functions --generate-pure-virtual-functions --generate-inline-functions -- -x c++ -std=c++14 + +class Test { +public: + virtual void a() = 0; + void b() = delete; +private: + void c() {} +}; diff --git a/tests/headers/underscore.hpp b/bindgen-tests/tests/headers/underscore.hpp similarity index 100% rename from tests/headers/underscore.hpp rename to bindgen-tests/tests/headers/underscore.hpp diff --git a/bindgen-tests/tests/headers/union-align.h b/bindgen-tests/tests/headers/union-align.h new file mode 100644 index 0000000000..5ed955f25e --- /dev/null +++ b/bindgen-tests/tests/headers/union-align.h @@ -0,0 +1,8 @@ +union Bar { + unsigned char foo; +} __attribute__ ((__aligned__ (16))); + + +union Baz { + union Bar bar; +}; diff --git a/tests/headers/union-in-ns.hpp b/bindgen-tests/tests/headers/union-in-ns.hpp similarity index 100% rename from tests/headers/union-in-ns.hpp rename to bindgen-tests/tests/headers/union-in-ns.hpp diff --git a/bindgen-tests/tests/headers/union_bitfield.h b/bindgen-tests/tests/headers/union_bitfield.h new file mode 100644 index 0000000000..4592a8973a --- /dev/null +++ b/bindgen-tests/tests/headers/union_bitfield.h @@ -0,0 +1,10 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq + +union U4 { + unsigned int derp:1; /* 0: 0 4 */ +}; + +union B { + unsigned int foo:31; /* 0: 0 4 */ + unsigned char bar:1; /* 0: 0 1 */ +}; diff --git a/tests/headers/union_dtor.hpp b/bindgen-tests/tests/headers/union_dtor.hpp similarity index 100% rename from tests/headers/union_dtor.hpp rename to bindgen-tests/tests/headers/union_dtor.hpp diff --git a/tests/headers/union_fields.hpp b/bindgen-tests/tests/headers/union_fields.hpp similarity index 100% rename from tests/headers/union_fields.hpp rename to bindgen-tests/tests/headers/union_fields.hpp diff --git a/tests/headers/union_template.hpp b/bindgen-tests/tests/headers/union_template.hpp similarity index 100% rename from tests/headers/union_template.hpp rename to bindgen-tests/tests/headers/union_template.hpp diff --git a/tests/headers/union_with_anon_struct.h b/bindgen-tests/tests/headers/union_with_anon_struct.h similarity index 100% rename from tests/headers/union_with_anon_struct.h rename to bindgen-tests/tests/headers/union_with_anon_struct.h diff --git a/tests/headers/union_with_anon_struct_bitfield.h b/bindgen-tests/tests/headers/union_with_anon_struct_bitfield.h similarity index 100% rename from tests/headers/union_with_anon_struct_bitfield.h rename to bindgen-tests/tests/headers/union_with_anon_struct_bitfield.h diff --git a/tests/headers/union_with_anon_union.h b/bindgen-tests/tests/headers/union_with_anon_union.h similarity index 100% rename from tests/headers/union_with_anon_union.h rename to bindgen-tests/tests/headers/union_with_anon_union.h diff --git a/tests/headers/union_with_anon_unnamed_struct.h b/bindgen-tests/tests/headers/union_with_anon_unnamed_struct.h similarity index 100% rename from tests/headers/union_with_anon_unnamed_struct.h rename to bindgen-tests/tests/headers/union_with_anon_unnamed_struct.h diff --git a/tests/headers/union_with_anon_unnamed_union.h b/bindgen-tests/tests/headers/union_with_anon_unnamed_union.h similarity index 100% rename from tests/headers/union_with_anon_unnamed_union.h rename to bindgen-tests/tests/headers/union_with_anon_unnamed_union.h diff --git a/tests/headers/union_with_big_member.h b/bindgen-tests/tests/headers/union_with_big_member.h similarity index 100% rename from tests/headers/union_with_big_member.h rename to bindgen-tests/tests/headers/union_with_big_member.h diff --git a/tests/headers/union_with_nesting.h b/bindgen-tests/tests/headers/union_with_nesting.h similarity index 100% rename from tests/headers/union_with_nesting.h rename to bindgen-tests/tests/headers/union_with_nesting.h diff --git a/bindgen-tests/tests/headers/union_with_non_copy_member.h b/bindgen-tests/tests/headers/union_with_non_copy_member.h new file mode 100644 index 0000000000..764820a46d --- /dev/null +++ b/bindgen-tests/tests/headers/union_with_non_copy_member.h @@ -0,0 +1,20 @@ +// bindgen-flags: --bindgen-wrapper-union 'WithBindgenGeneratedWrapper' --manually-drop-union 'WithManuallyDrop' --no-copy 'NonCopyType' + +struct NonCopyType { + int foo; +}; + +union WithBindgenGeneratedWrapper { + struct NonCopyType non_copy_type; + int bar; +}; + +union WithManuallyDrop { + struct NonCopyType non_copy_type; + int bar; +}; + +union WithDefaultWrapper { + struct NonCopyType non_copy_type; + int bar; +}; diff --git a/bindgen-tests/tests/headers/union_with_zero_sized_array.h b/bindgen-tests/tests/headers/union_with_zero_sized_array.h new file mode 100644 index 0000000000..ace745f26c --- /dev/null +++ b/bindgen-tests/tests/headers/union_with_zero_sized_array.h @@ -0,0 +1,5 @@ +union U { + char d0[0]; + char d1[1]; + char d2[2]; +}; diff --git a/tests/headers/unknown_attr.h b/bindgen-tests/tests/headers/unknown_attr.h similarity index 100% rename from tests/headers/unknown_attr.h rename to bindgen-tests/tests/headers/unknown_attr.h diff --git a/bindgen-tests/tests/headers/unsorted-items.h b/bindgen-tests/tests/headers/unsorted-items.h new file mode 100644 index 0000000000..23962d18d8 --- /dev/null +++ b/bindgen-tests/tests/headers/unsorted-items.h @@ -0,0 +1,15 @@ +int foo(); +typedef int number; +int bar(number x); +struct Point +{ + number x; + number y; +}; +struct Angle +{ + number a; + number b; +}; +int baz(struct Point point); +const number NUMBER = 42; diff --git a/bindgen-tests/tests/headers/use-core.h b/bindgen-tests/tests/headers/use-core.h new file mode 100644 index 0000000000..5ee0ac6f39 --- /dev/null +++ b/bindgen-tests/tests/headers/use-core.h @@ -0,0 +1,13 @@ +// bindgen-flags: --use-core --raw-line '#![cfg(not(target_os="windows"))] extern crate core;' --with-derive-hash --with-derive-partialeq --with-derive-eq + +struct foo { + int a, b; + void* bar; +}; + +union { + int bar; + long baz; +} bazz; + +typedef void (*fooFunction)(int bar); diff --git a/tests/headers/using.hpp b/bindgen-tests/tests/headers/using.hpp similarity index 100% rename from tests/headers/using.hpp rename to bindgen-tests/tests/headers/using.hpp diff --git a/bindgen-tests/tests/headers/va_list_aarch64_linux.h b/bindgen-tests/tests/headers/va_list_aarch64_linux.h new file mode 100644 index 0000000000..7d2206a76e --- /dev/null +++ b/bindgen-tests/tests/headers/va_list_aarch64_linux.h @@ -0,0 +1,4 @@ +// bindgen-flags: -- --target=aarch64-unknown-linux-gnu + +typedef __builtin_va_list va_list; +int vprintf(const char* format, va_list vlist); diff --git a/bindgen-tests/tests/headers/var-tracing.hpp b/bindgen-tests/tests/headers/var-tracing.hpp new file mode 100644 index 0000000000..ef002a00f5 --- /dev/null +++ b/bindgen-tests/tests/headers/var-tracing.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --allowlist-type Baz + +struct Bar { + const int m_baz; + Bar(int baz); +}; + +class Baz { + static const Bar FOO[]; +}; diff --git a/tests/headers/variadic-method.hpp b/bindgen-tests/tests/headers/variadic-method.hpp similarity index 100% rename from tests/headers/variadic-method.hpp rename to bindgen-tests/tests/headers/variadic-method.hpp diff --git a/bindgen-tests/tests/headers/variadic-union.hpp b/bindgen-tests/tests/headers/variadic-union.hpp new file mode 100644 index 0000000000..62ed49fcc9 --- /dev/null +++ b/bindgen-tests/tests/headers/variadic-union.hpp @@ -0,0 +1,3 @@ +template union _Variadic_union { + _Variadic_union() = default; +}; diff --git a/tests/headers/variadic_template_function.hpp b/bindgen-tests/tests/headers/variadic_template_function.hpp similarity index 100% rename from tests/headers/variadic_template_function.hpp rename to bindgen-tests/tests/headers/variadic_template_function.hpp diff --git a/bindgen-tests/tests/headers/vector.hpp b/bindgen-tests/tests/headers/vector.hpp new file mode 100644 index 0000000000..173aa02236 --- /dev/null +++ b/bindgen-tests/tests/headers/vector.hpp @@ -0,0 +1,9 @@ +struct foo { + __attribute__((__vector_size__(1 * sizeof(long long)))) long long mMember; +}; + +typedef float __m128 __attribute__ ((__vector_size__ (16))); +typedef double __m128d __attribute__((__vector_size__(16))); +typedef long long __m128i __attribute__((__vector_size__(16))); + +__m128 foo(__m128i, __m128d); diff --git a/tests/headers/virtual_dtor.hpp b/bindgen-tests/tests/headers/virtual_dtor.hpp similarity index 100% rename from tests/headers/virtual_dtor.hpp rename to bindgen-tests/tests/headers/virtual_dtor.hpp diff --git a/bindgen-tests/tests/headers/virtual_inheritance.hpp b/bindgen-tests/tests/headers/virtual_inheritance.hpp new file mode 100644 index 0000000000..b35378d881 --- /dev/null +++ b/bindgen-tests/tests/headers/virtual_inheritance.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --no-layout-tests +// FIXME: Enable layout tests when #465 is fixed. +class A { + int foo; +}; + +class B: public virtual A { + int bar; +}; + +class C: public virtual A { + int baz; +}; + +class D: public C, public B { + int bazz; +}; diff --git a/bindgen-tests/tests/headers/virtual_interface.hpp b/bindgen-tests/tests/headers/virtual_interface.hpp new file mode 100644 index 0000000000..00ab0737b7 --- /dev/null +++ b/bindgen-tests/tests/headers/virtual_interface.hpp @@ -0,0 +1,24 @@ +class PureVirtualIFace { +public: + virtual void Foo() = 0; + virtual void Bar(unsigned int) = 0; +}; + +class AnotherInterface { +public: + virtual void Baz() = 0; +}; + +class Implementation : public PureVirtualIFace { +public: + void Foo() override {} + void Bar(unsigned int) override {} +}; + +class DoubleImpl : public PureVirtualIFace, public AnotherInterface { +public: + void Foo() override {} + void Bar(unsigned int) override {} + + void Baz() override {} +}; diff --git a/tests/headers/virtual_overloaded.hpp b/bindgen-tests/tests/headers/virtual_overloaded.hpp similarity index 100% rename from tests/headers/virtual_overloaded.hpp rename to bindgen-tests/tests/headers/virtual_overloaded.hpp diff --git a/bindgen-tests/tests/headers/void_typedef.h b/bindgen-tests/tests/headers/void_typedef.h new file mode 100644 index 0000000000..405cbd0c46 --- /dev/null +++ b/bindgen-tests/tests/headers/void_typedef.h @@ -0,0 +1,9 @@ +typedef void VOID; + +typedef VOID ALSO_VOID; + +void this_api_returns_nothing(void); + +VOID this_api_also_returns_nothing(VOID); + +ALSO_VOID this_other_api_also_returns_nothing(ALSO_VOID); diff --git a/tests/headers/vtable_recursive_sig.hpp b/bindgen-tests/tests/headers/vtable_recursive_sig.hpp similarity index 100% rename from tests/headers/vtable_recursive_sig.hpp rename to bindgen-tests/tests/headers/vtable_recursive_sig.hpp diff --git a/bindgen-tests/tests/headers/wasm-constructor-returns.hpp b/bindgen-tests/tests/headers/wasm-constructor-returns.hpp new file mode 100644 index 0000000000..9e47032708 --- /dev/null +++ b/bindgen-tests/tests/headers/wasm-constructor-returns.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --generate constructors,types -- -fvisibility=default --target=wasm32-unknown-emscripten + +class Foo { +public: + Foo(int var); +}; + diff --git a/bindgen-tests/tests/headers/wasm-import-module.h b/bindgen-tests/tests/headers/wasm-import-module.h new file mode 100644 index 0000000000..db4fe85c8d --- /dev/null +++ b/bindgen-tests/tests/headers/wasm-import-module.h @@ -0,0 +1,3 @@ +// bindgen-flags: --wasm-import-module-name test-module + +void test_function(); \ No newline at end of file diff --git a/tests/headers/weird_bitfields.hpp b/bindgen-tests/tests/headers/weird_bitfields.hpp similarity index 97% rename from tests/headers/weird_bitfields.hpp rename to bindgen-tests/tests/headers/weird_bitfields.hpp index 7236d60a53..b2761a804a 100644 --- a/tests/headers/weird_bitfields.hpp +++ b/bindgen-tests/tests/headers/weird_bitfields.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --rustified-enum .* +// bindgen-flags: --rustified-enum ".*" // You can guess where this is taken from... enum nsStyleSVGOpacitySource { diff --git a/tests/headers/what_is_going_on.hpp b/bindgen-tests/tests/headers/what_is_going_on.hpp similarity index 100% rename from tests/headers/what_is_going_on.hpp rename to bindgen-tests/tests/headers/what_is_going_on.hpp diff --git a/bindgen-tests/tests/headers/win32-dtors.hpp b/bindgen-tests/tests/headers/win32-dtors.hpp new file mode 100644 index 0000000000..0f0f0e1604 --- /dev/null +++ b/bindgen-tests/tests/headers/win32-dtors.hpp @@ -0,0 +1,29 @@ +// bindgen-flags: -- --target=x86_64-pc-windows-msvc + +struct CppObj { + int x; + + CppObj(int x); + ~CppObj(); +}; + +struct CppObj2 { + int x; + + CppObj2(int x); + virtual ~CppObj2(); +}; + +struct CppObj3 : CppObj2 { + int x; + + CppObj3(int x); + virtual ~CppObj3(); +}; + +struct CppObj4 : CppObj2 { + int x; + + CppObj4(int x); + ~CppObj4(); +}; diff --git a/bindgen-tests/tests/headers/win32-thiscall.hpp b/bindgen-tests/tests/headers/win32-thiscall.hpp new file mode 100644 index 0000000000..4651f809a1 --- /dev/null +++ b/bindgen-tests/tests/headers/win32-thiscall.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --raw-line "#![cfg(not(test))]" -- --target=i686-pc-windows-msvc + +class Foo { + public: + void test(); + int test2(int var); +}; diff --git a/bindgen-tests/tests/headers/win32-thiscall_1_73.hpp b/bindgen-tests/tests/headers/win32-thiscall_1_73.hpp new file mode 100644 index 0000000000..8c240055b2 --- /dev/null +++ b/bindgen-tests/tests/headers/win32-thiscall_1_73.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --rust-target=1.73 --raw-line '#![cfg(target = "i686-pc-windows-msvc")]' -- --target=i686-pc-windows-msvc + +class Foo { + public: + void test(); + int test2(int var); +}; diff --git a/tests/headers/win32-thiscall_nightly.hpp b/bindgen-tests/tests/headers/win32-thiscall_nightly.hpp similarity index 100% rename from tests/headers/win32-thiscall_nightly.hpp rename to bindgen-tests/tests/headers/win32-thiscall_nightly.hpp diff --git a/bindgen-tests/tests/headers/win32-vectorcall-nightly.h b/bindgen-tests/tests/headers/win32-vectorcall-nightly.h new file mode 100644 index 0000000000..c099bb59a5 --- /dev/null +++ b/bindgen-tests/tests/headers/win32-vectorcall-nightly.h @@ -0,0 +1,3 @@ +// bindgen-flags: --rust-target nightly --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(abi_vectorcall)]' -- --target=x86_64-pc-windows-msvc + +int __vectorcall test_vectorcall(int a, int b); diff --git a/bindgen-tests/tests/headers/win32-vectorcall.h b/bindgen-tests/tests/headers/win32-vectorcall.h new file mode 100644 index 0000000000..3fe36f1004 --- /dev/null +++ b/bindgen-tests/tests/headers/win32-vectorcall.h @@ -0,0 +1,3 @@ +// bindgen-flags: -- --target=x86_64-pc-windows-msvc + +int __vectorcall test_vectorcall(int a, int b); diff --git a/bindgen-tests/tests/headers/with_array_pointers_arguments.h b/bindgen-tests/tests/headers/with_array_pointers_arguments.h new file mode 100644 index 0000000000..565b3cf678 --- /dev/null +++ b/bindgen-tests/tests/headers/with_array_pointers_arguments.h @@ -0,0 +1,10 @@ +// bindgen-flags: --use-array-pointers-in-arguments + +int test_fn(float a, int arr[20]); + +int test_fn2(const float arr[20], int b); + +typedef char defArr[20]; +typedef void foo(defArr a); + +void bar(defArr a); \ No newline at end of file diff --git a/bindgen-tests/tests/headers/without_array_pointers_arguments.h b/bindgen-tests/tests/headers/without_array_pointers_arguments.h new file mode 100644 index 0000000000..2f0668749b --- /dev/null +++ b/bindgen-tests/tests/headers/without_array_pointers_arguments.h @@ -0,0 +1,9 @@ + +int test_fn(float a, int arr[20]); + +int test_fn2(const float arr[20], int b); + +typedef char defArr[20]; +typedef void foo(defArr a); + +void bar(defArr a); \ No newline at end of file diff --git a/bindgen-tests/tests/headers/wrap-static-fns.h b/bindgen-tests/tests/headers/wrap-static-fns.h new file mode 100644 index 0000000000..a35e713f2b --- /dev/null +++ b/bindgen-tests/tests/headers/wrap-static-fns.h @@ -0,0 +1,91 @@ +// bindgen-flags: --wrap-static-fns +// bindgen-parse-callbacks: wrap-as-variadic-fn + +// to avoid polluting the expectation tests we put the stdarg.h behind a conditional +// variable only used in bindgen-integration +#ifdef USE_VA_HEADER +#include +#endif + +static inline int foo() { + return 11; +} +static int bar(); +static int bar() { + return 1; +} +inline int baz() { + return 2; +} + +static inline int takes_ptr(int* arg) { + return *arg + 1; +} + +static inline int takes_fn_ptr(int (*f)(int)) { + return f(1); +} + +static inline int takes_fn(int (f)(int)) { + return f(2); +} + +typedef int (func)(int); + +static inline int takes_alias(func f) { + return f(3); +} + +static inline int takes_qualified(const int *const *arg) { + return **arg; +} + +enum foo { + BAR = 0x0, +}; + +static inline enum foo takes_enum(const enum foo f) { + return f; +} + +static inline void nevermore() { + while (1) { } +} + +static inline int takes_fn_with_no_args(int(f)(void)) { + return f(); +} + +static inline int variadic(int x, ...) { + return x; +} + +// aarch64-linux has a bug, remove ifdef when it is solved: +// https://github.com/rust-lang/rust-bindgen/issues/3234 +#ifndef DISABLE_VA + +static inline void no_extra_argument(__builtin_va_list va) {} + +static inline int many_va_list(int i, __builtin_va_list va1, __builtin_va_list va2) { + return i; +} + +#ifndef USE_VA_HEADER +static inline int wrap_as_variadic_fn1(int i, __builtin_va_list va) { + return i; +} + +static inline void wrap_as_variadic_fn2(int i, __builtin_va_list va) {} +#else +static inline int wrap_as_variadic_fn1(int i, va_list va) { + int res = 0; + + for (int j = 0; j < i; j++) + res += (int) va_arg(va, int); + + return res; +} + +static inline void wrap_as_variadic_fn2(int i, va_list va) {} +#endif +#endif diff --git a/bindgen-tests/tests/headers/wrap_unsafe_ops_anon_union.hpp b/bindgen-tests/tests/headers/wrap_unsafe_ops_anon_union.hpp new file mode 100644 index 0000000000..34faea5d90 --- /dev/null +++ b/bindgen-tests/tests/headers/wrap_unsafe_ops_anon_union.hpp @@ -0,0 +1,22 @@ +// bindgen-flags: --wrap-unsafe-ops --no-layout-tests + +template +struct TErrorResult { + enum UnionState { + HasMessage, + HasException, + }; + int mResult; + struct Message; + struct DOMExceptionInfo; + union { + Message* mMessage; + DOMExceptionInfo* mDOMExceptionInfo; + }; + + bool mMightHaveUnreported; + UnionState mUnionState; +}; + +struct ErrorResult : public TErrorResult { +}; diff --git a/bindgen-tests/tests/headers/wrap_unsafe_ops_class.hpp b/bindgen-tests/tests/headers/wrap_unsafe_ops_class.hpp new file mode 100644 index 0000000000..e3d11c571b --- /dev/null +++ b/bindgen-tests/tests/headers/wrap_unsafe_ops_class.hpp @@ -0,0 +1,74 @@ +// bindgen-flags: --wrap-unsafe-ops --no-layout-tests + +class C { + int a; + // More than rust limits (32) + char big_array[33]; +}; + +class C_with_zero_length_array { + int a; + // More than rust limits (32) + char big_array[33]; + char zero_length_array[0]; +}; + +class C_with_zero_length_array_2 { + int a; + char zero_length_array[0]; +}; + +class C_with_incomplete_array { + int a; + // More than rust limits (32) + char big_array[33]; + char incomplete_array[]; +}; + +class C_with_incomplete_array_2 { + int a; + char incomplete_array[]; +}; + +class C_with_zero_length_array_and_incomplete_array { + int a; + // More than rust limits (32) + char big_array[33]; + char zero_length_array[0]; + char incomplete_array[]; +}; + +class C_with_zero_length_array_and_incomplete_array_2 { + int a; + char zero_length_array[0]; + char incomplete_array[]; +}; + +class WithDtor { + int b; + + ~WithDtor() {} +}; + +class IncompleteArrayNonCopiable { + void* whatever; + C incomplete_array[]; +}; + +union Union { + float d; + int i; +}; + +class WithUnion { + Union data; +}; + +class RealAbstractionWithTonsOfMethods { + void foo(); +public: + void bar() const; + void bar(); + void bar(int foo); + static void sta(); +}; diff --git a/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h b/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h new file mode 100644 index 0000000000..36a638ae2a --- /dev/null +++ b/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h @@ -0,0 +1,7 @@ +// bindgen-flags: --dynamic-loading TestLib --wrap-unsafe-ops + +int foo(int x, int y); +int bar(void *x); +int baz(); + +const int FLUX; diff --git a/bindgen-tests/tests/headers/wrap_unsafe_ops_objc_class.h b/bindgen-tests/tests/headers/wrap_unsafe_ops_objc_class.h new file mode 100644 index 0000000000..017795c85d --- /dev/null +++ b/bindgen-tests/tests/headers/wrap_unsafe_ops_objc_class.h @@ -0,0 +1,10 @@ +// bindgen-flags: --wrap-unsafe-ops -- -x objective-c +// bindgen-osx-only + +@class Foo; + +Foo* fooVar; + +@interface Foo +-(void)method; +@end diff --git a/bindgen-tests/tests/headers/zero-size-array-align.h b/bindgen-tests/tests/headers/zero-size-array-align.h new file mode 100644 index 0000000000..05b11bce57 --- /dev/null +++ b/bindgen-tests/tests/headers/zero-size-array-align.h @@ -0,0 +1,5 @@ +struct dm_deps { + unsigned count; + unsigned filler; + unsigned long long device[0]; +}; diff --git a/tests/headers/zero-sized-array.hpp b/bindgen-tests/tests/headers/zero-sized-array.hpp similarity index 100% rename from tests/headers/zero-sized-array.hpp rename to bindgen-tests/tests/headers/zero-sized-array.hpp diff --git a/bindgen-tests/tests/macro_fallback_test_headers/another_header.h b/bindgen-tests/tests/macro_fallback_test_headers/another_header.h new file mode 100644 index 0000000000..b0c40eb43f --- /dev/null +++ b/bindgen-tests/tests/macro_fallback_test_headers/another_header.h @@ -0,0 +1,10 @@ +#ifndef ANOTHER_HEADER_H +#define ANOTHER_HEADER_H + +#include + +#define SHOULD_NOT_GENERATE UINT64_C(~0) +#define MY_CONST UINT32_C(69) +#define NEGATIVE ~0 + +#endif diff --git a/bindgen-tests/tests/macro_fallback_test_headers/one_header.h b/bindgen-tests/tests/macro_fallback_test_headers/one_header.h new file mode 100644 index 0000000000..5058814bba --- /dev/null +++ b/bindgen-tests/tests/macro_fallback_test_headers/one_header.h @@ -0,0 +1,8 @@ +#ifndef ONE_HEADER_H +#define ONE_HEADER_H + +#include + +#define THE_CONST UINT32_C(28) + +#endif diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h new file mode 100644 index 0000000000..eb44e5fc58 --- /dev/null +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h @@ -0,0 +1,32 @@ +// Structs +void function_using_anonymous_struct(struct {} arg0); + +struct NamedStruct { +}; + +typedef struct NamedStruct AliasOfNamedStruct; + + +// Unions +void function_using_anonymous_union(union {} arg0); + +union NamedUnion { +}; + +typedef union NamedUnion AliasOfNamedUnion; + +// Enums + +// We don't include an anonymous enum because such enums +// are not visible outside the function, and thus tend not +// to be useful - bindgen doesn't handle them for this reason. + +enum NamedEnum { + Fish, +}; + +typedef enum NamedEnum AliasOfNamedEnum; + +// Functions + +void named_function(); diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp new file mode 100644 index 0000000000..1de8d99e4d --- /dev/null +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp @@ -0,0 +1,6 @@ +// Methods + +class SomeClass { +public: + void named_method(); +}; \ No newline at end of file diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs new file mode 100644 index 0000000000..a9a9523895 --- /dev/null +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs @@ -0,0 +1,510 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +use regex::Regex; + +use bindgen::callbacks::{ + DiscoveredItem, DiscoveredItemId, ParseCallbacks, SourceLocation, +}; +use bindgen::Builder; + +#[derive(Debug, Default)] +struct ItemDiscovery(Rc>); + +pub type ItemCache = HashMap; + +#[derive(Debug)] +pub struct DiscoveredInformation(DiscoveredItem, Option); + +impl ParseCallbacks for ItemDiscovery { + fn new_item_found( + &self, + id: DiscoveredItemId, + item: DiscoveredItem, + source_location: Option<&SourceLocation>, + ) { + self.0 + .borrow_mut() + .insert(id, DiscoveredInformation(item, source_location.cloned())); + } +} + +#[derive(Debug)] +pub struct ItemExpectations { + item: DiscoveredItem, + source_location: Option<(usize, usize, usize)>, +} + +impl ItemExpectations { + fn new( + item: DiscoveredItem, + line: usize, + col: usize, + byte_offset: usize, + ) -> Self { + Self { + item, + source_location: Some((line, col, byte_offset)), + } + } +} + +type ExpectationMap = HashMap; + +fn test_item_discovery_callback( + header: &str, + expected: &HashMap, +) { + let discovery = ItemDiscovery::default(); + let info = Rc::clone(&discovery.0); + + let mut header_path = env!("CARGO_MANIFEST_DIR").to_string(); + header_path.push_str(header); + + Builder::default() + .header(header_path) + .parse_callbacks(Box::new(discovery)) + .generate() + .expect("TODO: panic message"); + + compare_item_caches(&info.borrow(), expected, header); +} + +#[test] +fn test_item_discovery_callback_c() { + let expected = ExpectationMap::from([ + ( + DiscoveredItemId::new(10), + ItemExpectations::new( + DiscoveredItem::Struct { + original_name: Some("NamedStruct".to_string()), + final_name: "NamedStruct".to_string(), + }, + 4, + 8, + 73, + ), + ), + ( + DiscoveredItemId::new(11), + ItemExpectations::new( + DiscoveredItem::Alias { + alias_name: "AliasOfNamedStruct".to_string(), + alias_for: DiscoveredItemId::new(10), + }, + 7, + 28, + 118, + ), + ), + ( + DiscoveredItemId::new(20), + ItemExpectations::new( + DiscoveredItem::Union { + original_name: Some("NamedUnion".to_string()), + final_name: "NamedUnion".to_string(), + }, + 13, + 7, + 209, + ), + ), + ( + DiscoveredItemId::new(21), + ItemExpectations::new( + DiscoveredItem::Alias { + alias_name: "AliasOfNamedUnion".to_string(), + alias_for: DiscoveredItemId::new(20), + }, + 16, + 26, + 251, + ), + ), + ( + DiscoveredItemId::new(27), + ItemExpectations::new( + DiscoveredItem::Alias { + alias_name: "AliasOfNamedEnum".to_string(), + alias_for: DiscoveredItemId::new(24), + }, + 28, + 24, + 515, + ), + ), + ( + DiscoveredItemId::new(24), + ItemExpectations::new( + DiscoveredItem::Enum { + final_name: "NamedEnum".to_string(), + }, + 24, + 6, + 466, + ), + ), + ( + DiscoveredItemId::new(30), + ItemExpectations::new( + DiscoveredItem::Struct { + original_name: None, + final_name: "_bindgen_ty_*".to_string(), + }, + 2, + 38, + 48, + ), + ), + ( + DiscoveredItemId::new(40), + ItemExpectations::new( + DiscoveredItem::Union { + original_name: None, + final_name: "_bindgen_ty_*".to_string(), + }, + 11, + 37, + 186, + ), + ), + ( + DiscoveredItemId::new(41), + ItemExpectations::new( + DiscoveredItem::Function { + final_name: "named_function".to_string(), + }, + 32, + 6, + 553, + ), + ), + ]); + test_item_discovery_callback( + "/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h", &expected); +} + +#[test] +fn test_item_discovery_callback_cpp() { + let expected = ExpectationMap::from([ + ( + DiscoveredItemId::new(1), + ItemExpectations::new( + DiscoveredItem::Struct { + original_name: Some("SomeClass".to_string()), + final_name: "SomeClass".to_string(), + }, + 3, + 7, + 18, + ), + ), + ( + DiscoveredItemId::new(2), + ItemExpectations::new( + DiscoveredItem::Method { + final_name: "named_method".to_string(), + parent: DiscoveredItemId::new(1), + }, + 5, + 10, + 47, + ), + ), + ]); + test_item_discovery_callback( + "/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp", &expected); +} + +fn compare_item_caches( + generated: &ItemCache, + expected: &ExpectationMap, + expected_filename: &str, +) { + // We can't use a simple Eq::eq comparison because of two reasons: + // - anonymous structs/unions will have a final name generated by bindgen which may change + // if the header file or the bindgen logic is altered + // - aliases have a DiscoveredItemId that we can't directly compare for the same instability reasons + for expected_item in expected.values() { + let found = generated.iter().find(|(_generated_id, generated_item)| { + compare_item_info( + expected_item, + generated_item, + expected, + generated, + expected_filename, + ) + }); + + assert!( + found.is_some(), + "Missing Expected Item: {expected_item:#?}\n in {generated:#?}" + ); + } +} + +fn compare_item_info( + expected_item: &ItemExpectations, + generated_item: &DiscoveredInformation, + expected: &ExpectationMap, + generated: &ItemCache, + expected_filename: &str, +) -> bool { + if std::mem::discriminant(&expected_item.item) != + std::mem::discriminant(&generated_item.0) + { + return false; + } + + let is_a_match = match generated_item.0 { + DiscoveredItem::Struct { .. } => { + compare_struct_info(&expected_item.item, &generated_item.0) + } + DiscoveredItem::Union { .. } => { + compare_union_info(&expected_item.item, &generated_item.0) + } + DiscoveredItem::Alias { .. } => compare_alias_info( + &expected_item.item, + &generated_item.0, + expected, + generated, + expected_filename, + ), + DiscoveredItem::Enum { .. } => { + compare_enum_info(&expected_item.item, &generated_item.0) + } + DiscoveredItem::Function { .. } => { + compare_function_info(&expected_item.item, &generated_item.0) + } + DiscoveredItem::Method { .. } => { + compare_method_info(&expected_item.item, &generated_item.0) + } + }; + + if is_a_match { + // Compare source location + assert!( + generated_item.1.is_some() == + expected_item.source_location.is_some(), + "No source location provided when one was expected" + ); + if let Some(generated_location) = generated_item.1.as_ref() { + let expected_location = expected_item.source_location.unwrap(); + assert!( + generated_location + .file_name + .as_ref() + .expect("No filename provided") + .ends_with(expected_filename), + "Filename differed" + ); + assert_eq!( + ( + generated_location.line, + generated_location.col, + generated_location.byte_offset + ), + expected_location, + "Line/col/offsets differ" + ); + } + } + is_a_match +} + +pub fn compare_names(expected_name: &str, generated_name: &str) -> bool { + if let Ok(regex) = Regex::new(expected_name) { + regex.is_match(generated_name) + } else { + false + } +} + +pub fn compare_struct_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, +) -> bool { + let DiscoveredItem::Struct { + original_name: expected_original_name, + final_name: expected_final_name, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Struct { + original_name: generated_original_name, + final_name: generated_final_name, + } = generated_item + else { + unreachable!() + }; + + if !compare_names(expected_final_name, generated_final_name) { + return false; + } + + match (expected_original_name, generated_original_name) { + (None, None) => true, + (Some(expected_original_name), Some(generated_original_name)) => { + compare_names(expected_original_name, generated_original_name) + } + _ => false, + } +} + +pub fn compare_union_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, +) -> bool { + let DiscoveredItem::Union { + original_name: expected_original_name, + final_name: expected_final_name, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Union { + original_name: generated_original_name, + final_name: generated_final_name, + } = generated_item + else { + unreachable!() + }; + + if !compare_names(expected_final_name, generated_final_name) { + return false; + } + + match (expected_original_name, generated_original_name) { + (None, None) => true, + (Some(expected_original_name), Some(generated_original_name)) => { + compare_names(expected_original_name, generated_original_name) + } + _ => false, + } +} + +pub fn compare_enum_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, +) -> bool { + let DiscoveredItem::Enum { + final_name: expected_final_name, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Enum { + final_name: generated_final_name, + } = generated_item + else { + unreachable!() + }; + + if !compare_names(expected_final_name, generated_final_name) { + return false; + } + true +} + +pub fn compare_alias_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, + expected: &ExpectationMap, + generated: &ItemCache, + expected_filename: &str, +) -> bool { + let DiscoveredItem::Alias { + alias_name: expected_alias_name, + alias_for: expected_alias_for, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Alias { + alias_name: generated_alias_name, + alias_for: generated_alias_for, + } = generated_item + else { + unreachable!() + }; + + if !compare_names(expected_alias_name, generated_alias_name) { + return false; + } + + // Assumes correct test definition + let expected_aliased = expected.get(expected_alias_for).unwrap(); + + // We must have the aliased type in the cache + let Some(generated_aliased) = generated.get(generated_alias_for) else { + return false; + }; + + compare_item_info( + expected_aliased, + generated_aliased, + expected, + generated, + expected_filename, + ) +} + +pub fn compare_function_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, +) -> bool { + let DiscoveredItem::Function { + final_name: expected_final_name, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Function { + final_name: generated_final_name, + } = generated_item + else { + unreachable!() + }; + + if !compare_names(expected_final_name, generated_final_name) { + return false; + } + true +} + +pub fn compare_method_info( + expected_item: &DiscoveredItem, + generated_item: &DiscoveredItem, +) -> bool { + let DiscoveredItem::Method { + final_name: expected_final_name, + parent: expected_parent, + } = expected_item + else { + unreachable!() + }; + + let DiscoveredItem::Method { + final_name: generated_final_name, + parent: generated_parent, + } = generated_item + else { + unreachable!() + }; + + if expected_parent != generated_parent { + return false; + } + + if !compare_names(expected_final_name, generated_final_name) { + return false; + } + true +} diff --git a/bindgen-tests/tests/parse_callbacks/mod.rs b/bindgen-tests/tests/parse_callbacks/mod.rs new file mode 100644 index 0000000000..5fe8d90d4c --- /dev/null +++ b/bindgen-tests/tests/parse_callbacks/mod.rs @@ -0,0 +1,195 @@ +mod item_discovery_callback; + +use bindgen::callbacks::*; +use bindgen::FieldVisibilityKind; + +#[derive(Debug)] +pub struct RemovePrefixParseCallback { + pub remove_prefix: Option, +} + +impl RemovePrefixParseCallback { + pub fn new(prefix: &str) -> Self { + RemovePrefixParseCallback { + remove_prefix: Some(prefix.to_string()), + } + } +} + +impl ParseCallbacks for RemovePrefixParseCallback { + fn generated_name_override(&self, item_info: ItemInfo) -> Option { + if let Some(prefix) = &self.remove_prefix { + let (expected_prefix, expected_suffix) = match item_info.kind { + ItemKind::Function => ("function_", "_name"), + ItemKind::Var => ("var_", "_name"), + _ => todo!(), + }; + if let Some(name) = item_info.name.strip_prefix(prefix) { + assert!(name.starts_with(expected_prefix)); + assert!(name.ends_with(expected_suffix)); + return Some(name.to_string()); + } + } + None + } +} + +#[derive(Debug)] +pub struct PrefixLinkNameParseCallback { + pub prefix: Option, +} + +impl PrefixLinkNameParseCallback { + pub fn new(prefix: &str) -> Self { + PrefixLinkNameParseCallback { + prefix: Some(prefix.to_string()), + } + } +} + +impl ParseCallbacks for PrefixLinkNameParseCallback { + fn generated_link_name_override( + &self, + item_info: ItemInfo, + ) -> Option { + self.prefix + .as_deref() + .map(|prefix| format!("{prefix}{}", item_info.name)) + } +} + +#[derive(Debug)] +struct EnumVariantRename; + +impl ParseCallbacks for EnumVariantRename { + fn enum_variant_name( + &self, + _enum_name: Option<&str>, + original_variant_name: &str, + _variant_value: EnumVariantValue, + ) -> Option { + Some(format!("RENAMED_{original_variant_name}")) + } +} + +#[derive(Debug)] +struct BlocklistedTypeImplementsTrait; + +impl ParseCallbacks for BlocklistedTypeImplementsTrait { + fn blocklisted_type_implements_trait( + &self, + _name: &str, + derive_trait: DeriveTrait, + ) -> Option { + if derive_trait == DeriveTrait::Hash { + Some(ImplementsTrait::No) + } else { + Some(ImplementsTrait::Yes) + } + } +} + +#[derive(Debug)] +struct FieldVisibility { + default: FieldVisibilityKind, +} + +/// Implements the `field_visibility` function of the trait by checking if the +/// field name starts with `private_`. If it does, it makes it private, if it +/// doesn't, it makes it public, taking into account the default visibility. +impl ParseCallbacks for FieldVisibility { + fn field_visibility( + &self, + FieldInfo { field_name, .. }: FieldInfo, + ) -> Option { + match (self.default, field_name.starts_with("private_")) { + (FieldVisibilityKind::Private, false) => { + Some(FieldVisibilityKind::Public) + } + (FieldVisibilityKind::Public, true) => { + Some(FieldVisibilityKind::Private) + } + (FieldVisibilityKind::PublicCrate, _) => unimplemented!(), + _ => None, + } + } +} + +#[derive(Debug)] +struct TypeVisibility; + +/// Implements the `field_visibility` function of the trait by checking the +/// type name. Depending on name prefix, it will return a different visibility. +impl ParseCallbacks for TypeVisibility { + fn field_visibility( + &self, + FieldInfo { type_name, .. }: FieldInfo, + ) -> Option { + if type_name.starts_with("private_") { + Some(FieldVisibilityKind::Private) + } else if type_name.starts_with("pubcrate_") { + Some(FieldVisibilityKind::PublicCrate) + } else if type_name.starts_with("pub_") { + Some(FieldVisibilityKind::Public) + } else { + None + } + } +} + +#[derive(Debug)] +pub(super) struct WrapAsVariadicFn; + +impl ParseCallbacks for WrapAsVariadicFn { + fn wrap_as_variadic_fn(&self, name: &str) -> Option { + Some(name.to_owned() + "_wrapped") + } +} + +#[derive(Debug)] +pub(super) struct OperatorRename; + +impl ParseCallbacks for OperatorRename { + fn generated_name_override(&self, info: ItemInfo) -> Option { + if info.name == "operator=" { + Some("operatorequals".to_string()) + } else { + None + } + } +} + +pub fn lookup(cb: &str) -> Box { + match cb { + "enum-variant-rename" => Box::new(EnumVariantRename), + "blocklisted-type-implements-trait" => { + Box::new(BlocklistedTypeImplementsTrait) + } + "wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn), + "type-visibility" => Box::new(TypeVisibility), + "operator-rename" => Box::new(OperatorRename), + call_back => { + if let Some(prefix) = + call_back.strip_prefix("remove-function-prefix-") + { + let lnopc = RemovePrefixParseCallback::new(prefix); + Box::new(lnopc) + } else if let Some(prefix) = + call_back.strip_prefix("prefix-link-name-") + { + let plnpc = PrefixLinkNameParseCallback::new(prefix); + Box::new(plnpc) + } else if let Some(default) = + call_back.strip_prefix("field-visibility-default-") + { + Box::new(FieldVisibility { + default: default.parse().expect( + "unable to parse field-visibility-default callback", + ), + }) + } else { + panic!("Couldn't find name ParseCallbacks: {cb}") + } + } + } +} diff --git a/bindgen-tests/tests/quickchecking/.gitignore b/bindgen-tests/tests/quickchecking/.gitignore new file mode 100644 index 0000000000..03314f77b5 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/bindgen-tests/tests/quickchecking/Cargo.toml b/bindgen-tests/tests/quickchecking/Cargo.toml new file mode 100644 index 0000000000..b26ba3b392 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/Cargo.toml @@ -0,0 +1,34 @@ +lints.workspace = true + +[package] +name = "quickchecking" +description = "Bindgen property tests with quickcheck. Generate random valid C code and pass it to the csmith/predicate.py script" +version = "0.0.0" +publish = false +rust-version.workspace = true +edition.workspace = true + +[lib] +name = "quickchecking" +path = "src/lib.rs" + +[[bin]] +name = "quickchecking" +path = "src/bin.rs" + +[dependencies] +clap.workspace = true +quickcheck.workspace = true +tempfile.workspace = true + +[features] +# No features by default. +default = [] + +# Enable the generation of code that allows for zero sized arrays as struct +# fields. Until issues #684 and #1153 are resolved this can result in failing tests. +zero-sized-arrays = [] + +# Enable the generation of code that allows for long double types as struct +# fields. Until issue #550 is resolved this can result in failing tests. +long-doubles = [] diff --git a/bindgen-tests/tests/quickchecking/README.md b/bindgen-tests/tests/quickchecking/README.md new file mode 100644 index 0000000000..03aa0f2313 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/README.md @@ -0,0 +1,40 @@ +# Property tests for `bindgen` with `quickchecking` + +`quickchecking` generates random C headers to test `bindgen` +using the [`quickcheck`] property testing crate. When testing +`bindgen` with `quickchecking`, the generated header files are passed to +`bindgen`'s `csmith-fuzzing/predicate.py` script. If that script fails, +`quickchecking` panics, and you can report an issue containing the test case! + + + + + +- [Prerequisites](#prerequisites) +- [Running](#running) + + + +## Prerequisites + +Requires `python3` to be in `$PATH`. + +Many systems have `python3` by default but if your OS doesn't, its package +manager may make it available: + +``` +$ sudo apt install python3 +$ brew install python3 +$ # Etc... +``` + +## Running + +Run `quickchecking` binary to generate and test fuzzed C headers with +`cargo run`. Additional configuration is exposed through the binary's CLI. + +``` +$ cargo run --bin=quickchecking -- -h +``` + +[`quickcheck`]: https://github.com/BurntSushi/quickcheck diff --git a/bindgen-tests/tests/quickchecking/src/bin.rs b/bindgen-tests/tests/quickchecking/src/bin.rs new file mode 100644 index 0000000000..3072bc7b46 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/src/bin.rs @@ -0,0 +1,110 @@ +//! An application to run property tests for `bindgen` with _fuzzed_ C headers +//! using `quickcheck` +//! +//! ## Usage +//! +//! Print help +//! ```bash +//! $ cargo run --bin=quickchecking -- -h +//! ``` +//! +//! Run with default values +//! ```bash +//! $ cargo run --bin=quickchecking +//! ``` +//! +#![deny(missing_docs)] + +use clap::{Arg, ArgAction, Command}; +use std::path::PathBuf; + +// Parse CLI argument input for generation range. +fn parse_generate_range(v: &str) -> Result { + match v.parse::() { + Ok(v) => Ok(v), + Err(_) => Err(String::from( + "Generate range could not be converted to a usize.", + )), + } +} + +// Parse CLI argument input for tests count. +fn parse_tests_count(v: &str) -> Result { + match v.parse::() { + Ok(v) => Ok(v), + Err(_) => Err(String::from( + "Tests count could not be converted to a usize.", + )), + } +} + +// Parse CLI argument input for fuzzed headers output path. +fn parse_path(v: &str) -> Result { + let path = PathBuf::from(v); + if path.is_dir() { + Ok(path) + } else { + Err(String::from("Provided directory path does not exist.")) + } +} + +fn main() { + let matches = Command::new("quickchecking") + .version("0.2.0") + .about( + "Bindgen property tests with quickcheck. \ + Generate random valid C code and pass it to the \ + csmith/predicate.py script", + ) + .arg( + Arg::new("path") + .short('p') + .long("path") + .value_name("PATH") + .help( + "Optional. Preserve generated headers for inspection, \ + provide directory path for header output. [default: None] ", + ) + .action(ArgAction::Set) + .value_parser(parse_path), + ) + .arg( + Arg::new("range") + .short('r') + .long("range") + .value_name("RANGE") + .help( + "Sets the range quickcheck uses during generation. \ + Corresponds to things like arbitrary usize and \ + arbitrary vector length. This number doesn't have \ + to grow much for execution time to increase \ + significantly.", + ) + .action(ArgAction::Set) + .default_value("32") + .value_parser(parse_generate_range), + ) + .arg( + Arg::new("count") + .short('c') + .long("count") + .value_name("COUNT") + .help( + "Count / number of tests to run. Running a fuzzed \ + header through the predicate.py script can take a \ + long time, especially if the generation range is \ + large. Increase this number if you're willing to \ + wait a while.", + ) + .action(ArgAction::Set) + .default_value("2") + .value_parser(parse_tests_count), + ) + .get_matches(); + + let output_path = matches.get_one::("path").map(PathBuf::as_path); + let generate_range = *matches.get_one::("range").unwrap(); + let tests = *matches.get_one::("count").unwrap(); + + quickchecking::test_bindgen(generate_range, tests, output_path); +} diff --git a/bindgen-tests/tests/quickchecking/src/fuzzers.rs b/bindgen-tests/tests/quickchecking/src/fuzzers.rs new file mode 100644 index 0000000000..176636f66f --- /dev/null +++ b/bindgen-tests/tests/quickchecking/src/fuzzers.rs @@ -0,0 +1,633 @@ +use quickcheck::{Arbitrary, Gen}; +use std::fmt; +use std::fmt::Write as _; + +/// `BaseTypeC` is used in generation of C headers to represent the C language's +/// primitive types as well as `void*`. +#[derive(Debug, Clone)] +pub struct BaseTypeC { + /// String representation of C type. + pub def: String, +} + +/// `TypeQualifierC` is used in generation of C headers to represent qualifiers +/// such as `const`. +#[derive(Debug, Clone)] +pub struct TypeQualifierC { + /// String representation of C type qualifier. + pub def: String, +} + +/// `PointerLevelC` is used in generation of C headers to represent number of +/// `*` for pointer types. +#[derive(Debug, Clone)] +pub struct PointerLevelC { + /// String representation of C declaration's pointer level. + pub def: String, +} + +/// `ArrayDimensionC` is used in generation of C headers to represent number of +/// `[]` used to define array types. +#[derive(Debug, Clone)] +pub struct ArrayDimensionC { + /// String representation of C declaration's array dimension. + pub def: String, +} + +/// `BasicTypeDeclarationC` is used in generation of C headers to represent +/// declarations outside of function pointers that take the form +/// `BaseTypeC` + `TypeQualifierC` + `PointerLevelC` + `ident_id`. +#[derive(Debug, Clone)] +pub struct BasicTypeDeclarationC { + /// The declaration's base type, i.e. `int`. + pub type_name: BaseTypeC, + /// The declaration's type qualifier, i.e. `const`. + pub type_qualifier: TypeQualifierC, + /// The declaration's pointer level, i.e. `***`. + pub pointer_level: PointerLevelC, + /// The declaration's array dimension, i.e. [][][]. + pub array_dimension: ArrayDimensionC, + /// The declaration's identifier, i.e. `ident_N`. + pub ident_id: String, +} + +/// `StructDeclarationC` is used in generation of C headers to represent the +/// definition of a struct type. +#[derive(Debug, Clone)] +pub struct StructDeclarationC { + /// The declaration's fields. + pub fields: DeclarationListC, + /// The declaration's array dimension, i.e. [][][]. + pub array_dimension: ArrayDimensionC, + /// The declaration's identifier, i.e. `struct_N`. + pub ident_id: String, +} + +/// `UnionDeclarationC` is used in generation of C headers to represent the +/// definition of a union type. +#[derive(Debug, Clone)] +pub struct UnionDeclarationC { + /// The declaration's fields. + pub fields: DeclarationListC, + /// The declaration's array dimension, i.e. [][][]. + pub array_dimension: ArrayDimensionC, + /// The declaration's identifier, i.e. `union_N`. + pub ident_id: String, +} + +/// `FunctionPointerDeclarationC` is used in generation of C headers to represent +/// the definition of a function pointer type. +#[derive(Debug, Clone)] +pub struct FunctionPointerDeclarationC { + /// The function's type qualifier, i.e. `const`. + pub type_qualifier: TypeQualifierC, + /// The function's return type, i.e. `int`. + pub type_name: BaseTypeC, + /// The function's pointer level, i.e. `***`. + pub pointer_level: PointerLevelC, + /// The function's parameters. + pub params: ParameterListC, + /// The declaration's identifier, i.e. `func_ptr_N`. + pub ident_id: String, +} + +/// `FunctionPrototypeC` is used in generation of C headers to represent the +/// definition of a function prototype. +#[derive(Debug, Clone)] +pub struct FunctionPrototypeC { + /// The function's type qualifier, i.e. `const`. + pub type_qualifier: TypeQualifierC, + /// The function's return type, i.e. `int`. + pub type_name: BaseTypeC, + /// The function's pointer level, i.e. `***`. + pub pointer_level: PointerLevelC, + /// The function's parameters. + pub params: ParameterListC, + /// The prototype's identifier, i.e. `func_N`. + pub ident_id: String, +} + +/// `ParameterC` is used in generation of C headers to represent the +/// definition function parameters. +#[derive(Debug, Clone)] +pub struct ParameterC { + /// The parameter's type qualifier, i.e. `const`. + pub type_qualifier: TypeQualifierC, + /// The parameter's base type, i.e. `int`. + pub type_name: BaseTypeC, + /// The parameter's pointer level, i.e. `***`. + pub pointer_level: PointerLevelC, +} + +/// `ParameterListC` is used in generation of C headers to represent a list of +/// definitions of function parameters. +#[derive(Debug, Clone)] +pub struct ParameterListC { + /// Parameters that define a C function signature. + pub params: Vec, +} + +/// `DeclarationC` is used in generation of C headers to represent all supported +/// C type declarations allowed in the generated header. +#[derive(Debug, Clone)] +pub enum DeclarationC { + /// Function prototype declaration kind. + FunctionDecl(FunctionPrototypeC), + /// Function pointer declaration kind. + FunctionPtrDecl(FunctionPointerDeclarationC), + /// Struct declaration kind. + StructDecl(StructDeclarationC), + /// Union declaration kind. + UnionDecl(UnionDeclarationC), + /// Basic type declaration kind. + VariableDecl(BasicTypeDeclarationC), +} + +/// `DeclarationListC` is used in generation of C headers to represent a list of +/// declarations. +#[derive(Debug, Clone)] +pub struct DeclarationListC { + /// Grouping of C declarations. + pub decls: Vec, +} + +/// `HeaderC` is used in generation of C headers to represent a collection of +/// declarations. +#[derive(Clone)] +pub struct HeaderC { + /// The header's declarations. + pub def: DeclarationListC, +} + +/// `MakeUnique` is used in generation of C headers to make declaration +/// identifiers unique by incorporating the `stamp` parameter into it's name. +trait MakeUnique { + fn make_unique(&mut self, stamp: usize); +} + +/// `MakeUnique` is used in generation of C headers to make `DeclarationC` +/// identifiers unique. +impl MakeUnique for DeclarationC { + fn make_unique(&mut self, stamp: usize) { + match *self { + DeclarationC::FunctionDecl(ref mut d) => d.make_unique(stamp), + DeclarationC::FunctionPtrDecl(ref mut d) => d.make_unique(stamp), + DeclarationC::StructDecl(ref mut d) => d.make_unique(stamp), + DeclarationC::UnionDecl(ref mut d) => d.make_unique(stamp), + DeclarationC::VariableDecl(ref mut d) => d.make_unique(stamp), + } + } +} + +/// A qucickcheck trait for describing how `DeclarationC` types can be +/// randomly generated and shrunk. +impl Arbitrary for DeclarationC { + fn arbitrary(g: &mut Gen) -> DeclarationC { + match gen_range(g, 0, 5) { + 0 => DeclarationC::FunctionDecl(FunctionPrototypeC::arbitrary(g)), + 1 => DeclarationC::FunctionPtrDecl( + FunctionPointerDeclarationC::arbitrary(g), + ), + 2 => DeclarationC::StructDecl(StructDeclarationC::arbitrary(g)), + 3 => DeclarationC::UnionDecl(UnionDeclarationC::arbitrary(g)), + 4 => { + DeclarationC::VariableDecl(BasicTypeDeclarationC::arbitrary(g)) + } + _ => unreachable!(), + } + } +} + +/// Enables to string and format for `DeclarationC` types. +impl fmt::Display for DeclarationC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + DeclarationC::FunctionPtrDecl(ref d) => write!(f, "{d}"), + DeclarationC::StructDecl(ref d) => write!(f, "{d}"), + DeclarationC::UnionDecl(ref d) => write!(f, "{d}"), + DeclarationC::VariableDecl(ref d) => write!(f, "{d}"), + DeclarationC::FunctionDecl(ref d) => write!(f, "{d}"), + } + } +} + +/// A qucickcheck trait for describing how `DeclarationListC` types can be +/// randomly generated and shrunk. +impl Arbitrary for DeclarationListC { + fn arbitrary(g: &mut Gen) -> DeclarationListC { + DeclarationListC { + decls: Arbitrary::arbitrary(g), + } + } +} + +/// Enables to string and format for `DeclarationListC` types. +impl fmt::Display for DeclarationListC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for decl in &self.decls { + write!(f, "{decl}")?; + } + Ok(()) + } +} + +/// A quickcheck trait for describing how `BaseTypeC` types can be +/// randomly generated and shrunk. +impl Arbitrary for BaseTypeC { + fn arbitrary(g: &mut Gen) -> BaseTypeC { + // Special case `long double` until issue #550 is resolved. + let base_type = vec![ + "char", + "signed char", + "unsigned char", + "short", + "short int", + "signed short", + "signed short int", + "unsigned short", + "unsigned short int", + "int", + "signed", + "signed int", + "unsigned", + "unsigned int", + "long", + "long int", + "signed long", + "signed long int", + "unsigned long", + "unsigned long int", + "long long", + "long long int", + "signed long long", + "signed long long int", + "unsigned long long", + "unsigned long long int", + "float", + "double", + #[cfg(feature = "long-doubles")] + "long double", + "void*", + ]; + BaseTypeC { + def: String::from(*g.choose(&base_type).unwrap()), + } + } +} + +/// Enables to string and format for `BaseTypeC` types, +impl fmt::Display for BaseTypeC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.def) + } +} + +/// A qucickcheck trait for describing how `TypeQualifierC` types can be +/// randomly generated and shrunk. +impl Arbitrary for TypeQualifierC { + fn arbitrary(g: &mut Gen) -> TypeQualifierC { + let qualifier = vec!["const", ""]; + TypeQualifierC { + def: String::from(*g.choose(&qualifier).unwrap()), + } + } +} + +/// Enables to string and format for `TypeQualifierC` types. +impl fmt::Display for TypeQualifierC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.def) + } +} + +/// A qucickcheck trait for describing how `PointerLevelC` types can be +/// randomly generated and shrunk. +impl Arbitrary for PointerLevelC { + fn arbitrary(g: &mut Gen) -> PointerLevelC { + PointerLevelC { + // 16 is an arbitrary "not too big" number for capping pointer level. + def: (0..gen_range(g, 0, 16)).map(|_| "*").collect::(), + } + } +} + +/// Enables to string and format for `PointerLevelC` types. +impl fmt::Display for PointerLevelC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.def) + } +} + +/// A qucickcheck trait for describing how `ArrayDimensionC` types can be +/// randomly generated and shrunk. +impl Arbitrary for ArrayDimensionC { + fn arbitrary(g: &mut Gen) -> ArrayDimensionC { + // Keep these small, clang complains when they get too big. + let dimensions = gen_range(g, 0, 5); + let mut def = String::new(); + + let lower_bound = u64::from(cfg!(feature = "zero-sized-arrays")); + + for _ in 1..dimensions { + // 16 is an arbitrary "not too big" number for capping array size. + let _ = write!(def, "[{}]", gen_range(g, lower_bound, 16)); + } + ArrayDimensionC { def } + } +} + +/// Enables to string and format for `ArrayDimensionC` types. +impl fmt::Display for ArrayDimensionC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.def) + } +} + +/// `MakeUnique` is used in generation of C headers to make `BasicTypeDeclarationC` +/// identifiers unique. +impl MakeUnique for BasicTypeDeclarationC { + fn make_unique(&mut self, stamp: usize) { + let _ = write!(self.ident_id, "_{stamp}"); + } +} + +/// A qucickcheck trait for describing how `BasicTypeDeclarationC` types can be +/// randomly generated and shrunk. +impl Arbitrary for BasicTypeDeclarationC { + fn arbitrary(g: &mut Gen) -> BasicTypeDeclarationC { + BasicTypeDeclarationC { + type_qualifier: Arbitrary::arbitrary(g), + type_name: Arbitrary::arbitrary(g), + pointer_level: Arbitrary::arbitrary(g), + array_dimension: Arbitrary::arbitrary(g), + ident_id: format!("{}", usize::arbitrary(g)), + } + } +} + +/// Enables to string and format for `BasicTypeDeclarationC` types. +impl fmt::Display for BasicTypeDeclarationC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{} {} {} ident_{}{};", + self.type_qualifier, + self.type_name, + self.pointer_level, + self.ident_id, + self.array_dimension + ) + } +} + +/// `MakeUnique` is used in generation of C headers to make `StructDeclarationC` +/// identifiers unique. +impl MakeUnique for StructDeclarationC { + fn make_unique(&mut self, stamp: usize) { + let _ = write!(self.ident_id, "_{stamp}"); + } +} + +/// A qucickcheck trait for describing how `StructDeclarationC` types can be +/// randomly generated and shrunk. +impl Arbitrary for StructDeclarationC { + fn arbitrary(g: &mut Gen) -> StructDeclarationC { + // Reduce generator size as a method of putting a bound on recursion. + // When size < 1 the empty list is generated. + let reduced_size: usize = (g.size() / 2) + 1; + let mut decl_list: DeclarationListC = + Arbitrary::arbitrary(&mut Gen::new(reduced_size)); + let mut fields: DeclarationListC = DeclarationListC { decls: vec![] }; + + for (i, decl) in decl_list.decls.iter_mut().enumerate() { + match *decl { + DeclarationC::FunctionDecl(_) => {} + ref mut decl => { + decl.make_unique(i); + fields.decls.push(decl.clone()); + } + } + } + + StructDeclarationC { + fields, + ident_id: format!("{}", usize::arbitrary(g)), + array_dimension: Arbitrary::arbitrary(g), + } + } +} + +/// Enables to string and format for `StructDeclarationC` types. +impl fmt::Display for StructDeclarationC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "struct {{ {} }} struct_{}{};", + self.fields, self.ident_id, self.array_dimension + ) + } +} + +/// `MakeUnique` is used in generation of C headers to make `UnionDeclarationC` +/// identifiers unique. +impl MakeUnique for UnionDeclarationC { + fn make_unique(&mut self, stamp: usize) { + let _ = write!(self.ident_id, "_{stamp}"); + } +} + +/// A qucickcheck trait for describing how `UnionDeclarationC` types can be +/// randomly generated and shrunk. +impl Arbitrary for UnionDeclarationC { + fn arbitrary(g: &mut Gen) -> UnionDeclarationC { + // Reduce generator size as a method of putting a bound on recursion. + // When size < 1 the empty list is generated. + let reduced_size: usize = (g.size() / 2) + 1; + let mut decl_list: DeclarationListC = + Arbitrary::arbitrary(&mut Gen::new(reduced_size)); + let mut fields: DeclarationListC = DeclarationListC { decls: vec![] }; + + for (i, decl) in decl_list.decls.iter_mut().enumerate() { + match *decl { + DeclarationC::FunctionDecl(_) => {} + ref mut decl => { + decl.make_unique(i); + fields.decls.push(decl.clone()); + } + } + } + + UnionDeclarationC { + fields, + ident_id: format!("{}", usize::arbitrary(g)), + array_dimension: Arbitrary::arbitrary(g), + } + } +} + +/// Enables to string and format for `UnionDeclarationC` types. +impl fmt::Display for UnionDeclarationC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "union {{ {} }} union_{}{};", + self.fields, self.ident_id, self.array_dimension + ) + } +} + +/// `MakeUnique` is used in generation of C headers to make +/// `FunctionPointerDeclarationC` identifiers unique. +impl MakeUnique for FunctionPointerDeclarationC { + fn make_unique(&mut self, stamp: usize) { + let _ = write!(self.ident_id, "_{stamp}"); + } +} + +/// A qucickcheck trait for describing how `FunctionPointerDeclarationC` types can +/// be randomly generated and shrunk. +impl Arbitrary for FunctionPointerDeclarationC { + fn arbitrary(g: &mut Gen) -> FunctionPointerDeclarationC { + FunctionPointerDeclarationC { + type_qualifier: Arbitrary::arbitrary(g), + type_name: Arbitrary::arbitrary(g), + pointer_level: Arbitrary::arbitrary(g), + params: Arbitrary::arbitrary(g), + ident_id: format!("{}", usize::arbitrary(g)), + } + } +} + +/// Enables to string and format for `FunctionPointerDeclarationC` types. +impl fmt::Display for FunctionPointerDeclarationC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{} {} {} (*func_ptr_{})({});", + self.type_qualifier, + self.type_name, + self.pointer_level, + self.ident_id, + self.params + ) + } +} + +/// `MakeUnique` is used in generation of C headers to make `FunctionPrototypeC` +/// identifiers unique. +impl MakeUnique for FunctionPrototypeC { + fn make_unique(&mut self, stamp: usize) { + let _ = write!(self.ident_id, "_{stamp}"); + } +} + +/// A qucickcheck trait for describing how `FunctionPrototypeC` types can be +/// randomly generated and shrunk. +impl Arbitrary for FunctionPrototypeC { + fn arbitrary(g: &mut Gen) -> FunctionPrototypeC { + FunctionPrototypeC { + type_qualifier: Arbitrary::arbitrary(g), + type_name: Arbitrary::arbitrary(g), + pointer_level: Arbitrary::arbitrary(g), + params: Arbitrary::arbitrary(g), + ident_id: format!("{}", usize::arbitrary(g)), + } + } +} + +/// Enables to string and format for `FunctionPrototypeC` types. +impl fmt::Display for FunctionPrototypeC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{} {} {} func_{}({});", + self.type_qualifier, + self.type_name, + self.pointer_level, + self.ident_id, + self.params + ) + } +} + +/// A qucickcheck trait for describing how `ParameterC` types can be +/// randomly generated and shrunk. +impl Arbitrary for ParameterC { + fn arbitrary(g: &mut Gen) -> ParameterC { + ParameterC { + type_qualifier: Arbitrary::arbitrary(g), + type_name: Arbitrary::arbitrary(g), + pointer_level: Arbitrary::arbitrary(g), + } + } +} + +/// Enables to string and format for `ParameterC` types. +impl fmt::Display for ParameterC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{} {} {}", + self.type_qualifier, self.type_name, self.pointer_level + ) + } +} + +/// A qucickcheck trait for describing how `ParameterListC` types can be +/// randomly generated and shrunk. +impl Arbitrary for ParameterListC { + fn arbitrary(g: &mut Gen) -> ParameterListC { + ParameterListC { + params: Arbitrary::arbitrary(g), + } + } +} + +/// Enables to string and format for `ParameterListC` types. +impl fmt::Display for ParameterListC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, p) in self.params.iter().enumerate() { + match i { + 0 => write!(f, "{p}")?, + _ => write!(f, ",{p}")?, + } + } + Ok(()) + } +} + +/// A qucickcheck trait for describing how `HeaderC` types can be +/// randomly generated and shrunk. +impl Arbitrary for HeaderC { + fn arbitrary(g: &mut Gen) -> HeaderC { + let mut decl_list: DeclarationListC = Arbitrary::arbitrary(g); + for (i, decl) in decl_list.decls.iter_mut().enumerate() { + decl.make_unique(i); + } + HeaderC { def: decl_list } + } +} + +/// Enables to string and format for `HeaderC` types. +impl fmt::Display for HeaderC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for decl in &self.def.decls { + write!(f, "{decl}")?; + } + Ok(()) + } +} + +/// Use Display trait for Debug so that any failing property tests report +/// generated C code rather than the data structures that contain it. +impl fmt::Debug for HeaderC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self}") + } +} + +/// FIXME: is this actually uniform? +fn gen_range(gen: &mut Gen, lo: u64, hi: u64) -> u64 { + let len = hi - lo; + (u64::arbitrary(gen) % len) + lo +} diff --git a/bindgen-tests/tests/quickchecking/src/lib.rs b/bindgen-tests/tests/quickchecking/src/lib.rs new file mode 100644 index 0000000000..7567a3bea6 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/src/lib.rs @@ -0,0 +1,108 @@ +//! A library to generate __fuzzed__ C headers for use with `quickcheck` +//! +//! ## Example +//! +//! ```rust +//! use quickcheck::{Arbitrary, Gen}; +//! use quickchecking::fuzzers; +//! +//! let generate_range: usize = 10; // Determines things like the length of +//! // arbitrary vectors generated. +//! let header = fuzzers::HeaderC::arbitrary(&mut Gen::new(generate_range)); +//! println!("{header}"); +//! ``` +#![deny(missing_docs)] + +use quickcheck::{Gen, QuickCheck, TestResult}; +use std::error::Error; +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::process::{Command, Output}; +use std::sync::Mutex; +use tempfile::Builder; + +/// Contains definitions of and impls for types used to fuzz C declarations. +pub mod fuzzers; + +// Global singleton, manages context across tests. For now that context is +// only the output_path for inspecting fuzzed headers (if specified). +struct Context { + output_path: Option, +} + +// Initialize global context. +static CONTEXT: Mutex = Mutex::new(Context { output_path: None }); + +// Passes fuzzed header to the `csmith-fuzzing/predicate.py` script, returns +// output of the associated command. +fn run_predicate_script( + header: &fuzzers::HeaderC, +) -> Result> { + let dir = Builder::new().prefix("bindgen_prop").tempdir()?; + let header_path = dir.path().join("prop_test.h"); + + let mut header_file = File::create(&header_path)?; + header_file.write_all(header.to_string().as_bytes())?; + header_file.sync_all()?; + + let header_path_string = header_path + .into_os_string() + .into_string() + .map_err(|_| "error converting path into String")?; + + let mut predicate_script_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + predicate_script_path.push("../../csmith-fuzzing/predicate.py"); + + let predicate_script_path_string = predicate_script_path + .into_os_string() + .into_string() + .map_err(|_| "error converting path into String")?; + + // Copy generated temp files to output_path directory for inspection. + // If `None`, output path not specified, don't copy. + if let Some(ref path) = CONTEXT.lock().unwrap().output_path { + Command::new("cp") + .arg("-a") + .arg(dir.path().to_str().unwrap()) + .arg(path) + .output()?; + } + + Ok(Command::new(predicate_script_path_string) + .arg(&header_path_string) + .output()?) +} + +// Generatable property. Pass generated headers off to run through the +// `csmith-fuzzing/predicate.py` script. Success is measured by the success +// status of that command. +#[allow(clippy::needless_pass_by_value)] +fn bindgen_prop(header: fuzzers::HeaderC) -> TestResult { + match run_predicate_script(&header) { + Ok(o) => TestResult::from_bool(o.status.success()), + Err(e) => { + println!("{e:?}"); + TestResult::from_bool(false) + } + } +} + +/// Instantiate a Quickcheck object and use it to run property tests using +/// fuzzed C headers generated with types defined in the `fuzzers` module. +/// Success/Failure is dictated by the result of passing the fuzzed headers +/// to the `csmith-fuzzing/predicate.py` script. +pub fn test_bindgen( + generate_range: usize, + tests: u64, + output_path: Option<&Path>, +) { + if let Some(path) = output_path { + CONTEXT.lock().unwrap().output_path = Some(path.display().to_string()); + } + + QuickCheck::new() + .tests(tests) + .gen(Gen::new(generate_range)) + .quickcheck(bindgen_prop as fn(fuzzers::HeaderC) -> TestResult); +} diff --git a/bindgen-tests/tests/quickchecking/tests/fuzzed-c-headers.rs b/bindgen-tests/tests/quickchecking/tests/fuzzed-c-headers.rs new file mode 100644 index 0000000000..0735a70c47 --- /dev/null +++ b/bindgen-tests/tests/quickchecking/tests/fuzzed-c-headers.rs @@ -0,0 +1,90 @@ +use quickcheck::{Arbitrary, Gen}; +use quickchecking::fuzzers::{ + ArrayDimensionC, BaseTypeC, BasicTypeDeclarationC, DeclarationC, + DeclarationListC, FunctionPointerDeclarationC, FunctionPrototypeC, HeaderC, + ParameterC, ParameterListC, PointerLevelC, StructDeclarationC, + TypeQualifierC, UnionDeclarationC, +}; +#[test] +fn test_declaraion_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: DeclarationC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_declaraion_list_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: DeclarationListC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_base_type_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: BaseTypeC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_type_qualifier_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: TypeQualifierC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_pointer_level_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: PointerLevelC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_array_dimension_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: ArrayDimensionC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_basic_type_declaration_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: BasicTypeDeclarationC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_struct_declaration_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: StructDeclarationC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_union_declaration_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: UnionDeclarationC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_function_pointer_declaration_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: FunctionPointerDeclarationC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_function_prototype_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: FunctionPrototypeC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_parameter_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: ParameterC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_parameter_list_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: ParameterListC = Arbitrary::arbitrary(gen); +} + +#[test] +fn test_header_c_does_not_panic() { + let gen = &mut Gen::new(50); + let _: HeaderC = Arbitrary::arbitrary(gen); +} diff --git a/bindgen-tests/tests/rustfmt.toml b/bindgen-tests/tests/rustfmt.toml new file mode 100644 index 0000000000..2564ccb5d7 --- /dev/null +++ b/bindgen-tests/tests/rustfmt.toml @@ -0,0 +1,3 @@ +normalize_doc_attributes = true +max_width = 80 +binop_separator = "back" diff --git a/tests/stylo.hpp b/bindgen-tests/tests/stylo.hpp similarity index 99% rename from tests/stylo.hpp rename to bindgen-tests/tests/stylo.hpp index d6eabc3542..8810290365 100644 --- a/tests/stylo.hpp +++ b/bindgen-tests/tests/stylo.hpp @@ -103701,7 +103701,7 @@ class nsIExpandedPrincipal : public nsISupports { template struct COMTypeInfo; - virtual nsresult GetWhiteList(nsTArray > **aWhiteList) = 0; + virtual nsresult GetAllowList(nsTArray > **anAllowList) = 0; }; diff --git a/bindgen-tests/tests/stylo_sanity.rs b/bindgen-tests/tests/stylo_sanity.rs new file mode 100755 index 0000000000..7b94e2989e --- /dev/null +++ b/bindgen-tests/tests/stylo_sanity.rs @@ -0,0 +1,555 @@ +/// A sanity test that we can generate bindings for Stylo. +/// +/// We don't assert on expected output because its just too big. The output will +/// change too often, and it won't be clear what is going on at a glance, unlike +/// the other tests with smaller input headers. +/// +/// This test is relatively slow, so we also only run it in release mode. +/// +/// Finally, uncomment the `panic!` at the bottom of the test to get logs timing +/// how long bindings generation takes for Stylo. Stylo bindings generation +/// takes too long to be a proper `#[bench]`. +#[test] +#[cfg(not(any( + debug_assertions, + feature = "__testing_only_extra_assertions", +)))] +#[cfg(any( + feature = "__testing_only_libclang_9", + feature = "__testing_only_libclang_16" +))] +fn sanity_check_can_generate_stylo_bindings() { + use std::time::Instant; + + let then = Instant::now(); + + bindgen::builder() + .time_phases(true) + .disable_header_comment() + .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/stylo.hpp")) + .allowlist_function("Servo_.*") + .allowlist_function("Gecko_.*") + .blocklist_type("nsACString_internal") + .blocklist_type("nsAString_internal") + .blocklist_type("mozilla::css::URLValue") + .blocklist_type("RawGeckoAnimationPropertySegment") + .blocklist_type("RawGeckoComputedTiming") + .blocklist_type("RawGeckoDocument") + .blocklist_type("RawGeckoElement") + .blocklist_type("RawGeckoKeyframeList") + .blocklist_type("RawGeckoComputedKeyframeValuesList") + .blocklist_type("RawGeckoFontFaceRuleList") + .blocklist_type("RawGeckoNode") + .blocklist_type("RawGeckoAnimationValueList") + .blocklist_type("RawServoAnimationValue") + .blocklist_type("RawServoAnimationValueMap") + .blocklist_type("RawServoDeclarationBlock") + .blocklist_type("RawGeckoPresContext") + .blocklist_type("RawGeckoPresContextOwned") + .blocklist_type("RawGeckoStyleAnimationList") + .blocklist_type("RawGeckoURLExtraData") + .blocklist_type("RefPtr") + .blocklist_type("CSSPseudoClassType") + .blocklist_type("TraversalRootBehavior") + .blocklist_type("ComputedTimingFunction_BeforeFlag") + .blocklist_type("FontFamilyList") + .blocklist_type("FontFamilyType") + .blocklist_type("Keyframe") + .blocklist_type("ServoBundledURI") + .blocklist_type("ServoElementSnapshot") + .blocklist_type("SheetParsingMode") + .blocklist_type("StyleBasicShape") + .blocklist_type("StyleBasicShapeType") + .blocklist_type("StyleShapeSource") + .blocklist_type("nsCSSFontFaceRule") + .blocklist_type("nsCSSKeyword") + .blocklist_type("nsCSSPropertyID") + .blocklist_type("nsCSSShadowArray") + .blocklist_type("nsCSSUnit") + .blocklist_type("nsCSSValue") + .blocklist_type("nsCSSValueSharedList") + .blocklist_type("nsChangeHint") + .blocklist_type("nsCursorImage") + .blocklist_type("nsFont") + .blocklist_type("nsIAtom") + .blocklist_type("nsMediaFeature") + .blocklist_type("nsRestyleHint") + .blocklist_type("nsStyleBackground") + .blocklist_type("nsStyleBorder") + .blocklist_type("nsStyleColor") + .blocklist_type("nsStyleColumn") + .blocklist_type("nsStyleContent") + .blocklist_type("nsStyleContentData") + .blocklist_type("nsStyleContentType") + .blocklist_type("nsStyleContext") + .blocklist_type("nsStyleCoord") + .blocklist_type("nsStyleCoord_Calc") + .blocklist_type("nsStyleCoord_CalcValue") + .blocklist_type("nsStyleDisplay") + .blocklist_type("nsStyleEffects") + .blocklist_type("nsStyleFilter") + .blocklist_type("nsStyleFont") + .blocklist_type("nsStyleGradient") + .blocklist_type("nsStyleGradientStop") + .blocklist_type("nsStyleImage") + .blocklist_type("nsStyleImageLayers") + .blocklist_type("nsStyleImageLayers_Layer") + .blocklist_type("nsStyleImageLayers_LayerType") + .blocklist_type("nsStyleImageRequest") + .blocklist_type("nsStyleList") + .blocklist_type("nsStyleMargin") + .blocklist_type("nsStyleOutline") + .blocklist_type("nsStylePadding") + .blocklist_type("nsStylePosition") + .blocklist_type("nsStyleQuoteValues") + .blocklist_type("nsStyleSVG") + .blocklist_type("nsStyleSVGPaint") + .blocklist_type("nsStyleSVGReset") + .blocklist_type("nsStyleTable") + .blocklist_type("nsStyleTableBorder") + .blocklist_type("nsStyleText") + .blocklist_type("nsStyleTextReset") + .blocklist_type("nsStyleUIReset") + .blocklist_type("nsStyleUnion") + .blocklist_type("nsStyleUnit") + .blocklist_type("nsStyleUserInterface") + .blocklist_type("nsStyleVariables") + .blocklist_type("nsStyleVisibility") + .blocklist_type("nsStyleXUL") + .blocklist_type("nsTimingFunction") + .blocklist_type("nscolor") + .blocklist_type("nscoord") + .blocklist_type("nsresult") + .blocklist_type("Loader") + .blocklist_type("ServoStyleSheet") + .blocklist_type("EffectCompositor_CascadeLevel") + .blocklist_type("UpdateAnimationsTasks") + .blocklist_type("nsTArrayBorrowed_uintptr_t") + .blocklist_type("ServoCssRulesStrong") + .blocklist_type("ServoCssRulesBorrowed") + .blocklist_type("ServoCssRulesBorrowedOrNull") + .blocklist_type("ServoCssRules") + .blocklist_type("RawServoStyleSheetStrong") + .blocklist_type("RawServoStyleSheetBorrowed") + .blocklist_type("RawServoStyleSheetBorrowedOrNull") + .blocklist_type("RawServoStyleSheet") + .blocklist_type("ServoComputedValuesStrong") + .blocklist_type("ServoComputedValuesBorrowed") + .blocklist_type("ServoComputedValuesBorrowedOrNull") + .blocklist_type("ServoComputedValues") + .blocklist_type("RawServoDeclarationBlockStrong") + .blocklist_type("RawServoDeclarationBlockBorrowed") + .blocklist_type("RawServoDeclarationBlockBorrowedOrNull") + .blocklist_type("RawServoStyleRuleStrong") + .blocklist_type("RawServoStyleRuleBorrowed") + .blocklist_type("RawServoStyleRuleBorrowedOrNull") + .blocklist_type("RawServoStyleRule") + .blocklist_type("RawServoImportRuleStrong") + .blocklist_type("RawServoImportRuleBorrowed") + .blocklist_type("RawServoImportRuleBorrowedOrNull") + .blocklist_type("RawServoImportRule") + .blocklist_type("RawServoAnimationValueStrong") + .blocklist_type("RawServoAnimationValueBorrowed") + .blocklist_type("RawServoAnimationValueBorrowedOrNull") + .blocklist_type("RawServoAnimationValueMapStrong") + .blocklist_type("RawServoAnimationValueMapBorrowed") + .blocklist_type("RawServoAnimationValueMapBorrowedOrNull") + .blocklist_type("RawServoMediaListStrong") + .blocklist_type("RawServoMediaListBorrowed") + .blocklist_type("RawServoMediaListBorrowedOrNull") + .blocklist_type("RawServoMediaList") + .blocklist_type("RawServoMediaRuleStrong") + .blocklist_type("RawServoMediaRuleBorrowed") + .blocklist_type("RawServoMediaRuleBorrowedOrNull") + .blocklist_type("RawServoMediaRule") + .blocklist_type("RawServoNamespaceRuleStrong") + .blocklist_type("RawServoNamespaceRuleBorrowed") + .blocklist_type("RawServoNamespaceRuleBorrowedOrNull") + .blocklist_type("RawServoNamespaceRule") + .blocklist_type("RawServoStyleSetOwned") + .blocklist_type("RawServoStyleSetOwnedOrNull") + .blocklist_type("RawServoStyleSetBorrowed") + .blocklist_type("RawServoStyleSetBorrowedOrNull") + .blocklist_type("RawServoStyleSetBorrowedMut") + .blocklist_type("RawServoStyleSetBorrowedMutOrNull") + .blocklist_type("RawServoStyleSet") + .blocklist_type("StyleChildrenIteratorOwned") + .blocklist_type("StyleChildrenIteratorOwnedOrNull") + .blocklist_type("StyleChildrenIteratorBorrowed") + .blocklist_type("StyleChildrenIteratorBorrowedOrNull") + .blocklist_type("StyleChildrenIteratorBorrowedMut") + .blocklist_type("StyleChildrenIteratorBorrowedMutOrNull") + .blocklist_type("StyleChildrenIterator") + .blocklist_type("ServoElementSnapshotOwned") + .blocklist_type("ServoElementSnapshotOwnedOrNull") + .blocklist_type("ServoElementSnapshotBorrowed") + .blocklist_type("ServoElementSnapshotBorrowedOrNull") + .blocklist_type("ServoElementSnapshotBorrowedMut") + .blocklist_type("ServoElementSnapshotBorrowedMutOrNull") + .blocklist_type("RawGeckoNodeBorrowed") + .blocklist_type("RawGeckoNodeBorrowedOrNull") + .blocklist_type("RawGeckoElementBorrowed") + .blocklist_type("RawGeckoElementBorrowedOrNull") + .blocklist_type("RawGeckoDocumentBorrowed") + .blocklist_type("RawGeckoDocumentBorrowedOrNull") + .blocklist_type("RawServoDeclarationBlockStrongBorrowed") + .blocklist_type("RawServoDeclarationBlockStrongBorrowedOrNull") + .blocklist_type("RawGeckoPresContextBorrowed") + .blocklist_type("RawGeckoPresContextBorrowedOrNull") + .blocklist_type("RawGeckoStyleAnimationListBorrowed") + .blocklist_type("RawGeckoStyleAnimationListBorrowedOrNull") + .blocklist_type("nsCSSValueBorrowed") + .blocklist_type("nsCSSValueBorrowedOrNull") + .blocklist_type("nsCSSValueBorrowedMut") + .blocklist_type("nsCSSValueBorrowedMutOrNull") + .blocklist_type("nsTimingFunctionBorrowed") + .blocklist_type("nsTimingFunctionBorrowedOrNull") + .blocklist_type("nsTimingFunctionBorrowedMut") + .blocklist_type("nsTimingFunctionBorrowedMutOrNull") + .blocklist_type("RawGeckoAnimationPropertySegmentBorrowed") + .blocklist_type("RawGeckoAnimationPropertySegmentBorrowedOrNull") + .blocklist_type("RawGeckoAnimationPropertySegmentBorrowedMut") + .blocklist_type("RawGeckoAnimationPropertySegmentBorrowedMutOrNull") + .blocklist_type("RawGeckoAnimationValueListBorrowed") + .blocklist_type("RawGeckoAnimationValueListBorrowedOrNull") + .blocklist_type("RawGeckoAnimationValueListBorrowedMut") + .blocklist_type("RawGeckoAnimationValueListBorrowedMutOrNull") + .blocklist_type("RawGeckoComputedTimingBorrowed") + .blocklist_type("RawGeckoComputedTimingBorrowedOrNull") + .blocklist_type("RawGeckoComputedTimingBorrowedMut") + .blocklist_type("RawGeckoComputedTimingBorrowedMutOrNull") + .blocklist_type("RawGeckoKeyframeListBorrowed") + .blocklist_type("RawGeckoKeyframeListBorrowedOrNull") + .blocklist_type("RawGeckoKeyframeListBorrowedMut") + .blocklist_type("RawGeckoKeyframeListBorrowedMutOrNull") + .blocklist_type("RawGeckoComputedKeyframeValuesListBorrowed") + .blocklist_type("RawGeckoComputedKeyframeValuesListBorrowedOrNull") + .blocklist_type("RawGeckoComputedKeyframeValuesListBorrowedMut") + .blocklist_type("RawGeckoComputedKeyframeValuesListBorrowedMutOrNull") + .blocklist_type("RawGeckoFontFaceRuleListBorrowed") + .blocklist_type("RawGeckoFontFaceRuleListBorrowedOrNull") + .blocklist_type("RawGeckoFontFaceRuleListBorrowedMut") + .blocklist_type("RawGeckoFontFaceRuleListBorrowedMutOrNull") + .raw_line(r#"pub use nsstring::{nsACString, nsAString, nsString};"#) + .raw_line(r#"type nsACString_internal = nsACString;"#) + .raw_line(r#"type nsAString_internal = nsAString;"#) + .raw_line(r#"use gecko_bindings::structs::mozilla::css::URLValue;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoAnimationPropertySegment;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoComputedTiming;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoDocument;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoElement;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoKeyframeList;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoFontFaceRuleList;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoNode;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoAnimationValueList;"#) + .raw_line(r#"use gecko_bindings::structs::RawServoAnimationValue;"#) + .raw_line(r#"use gecko_bindings::structs::RawServoAnimationValueMap;"#) + .raw_line(r#"use gecko_bindings::structs::RawServoDeclarationBlock;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoPresContext;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoPresContextOwned;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoStyleAnimationList;"#) + .raw_line(r#"use gecko_bindings::structs::RawGeckoURLExtraData;"#) + .raw_line(r#"use gecko_bindings::structs::RefPtr;"#) + .raw_line(r#"use gecko_bindings::structs::CSSPseudoClassType;"#) + .raw_line(r#"use gecko_bindings::structs::TraversalRootBehavior;"#) + .raw_line(r#"use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;"#) + .raw_line(r#"use gecko_bindings::structs::FontFamilyList;"#) + .raw_line(r#"use gecko_bindings::structs::FontFamilyType;"#) + .raw_line(r#"use gecko_bindings::structs::Keyframe;"#) + .raw_line(r#"use gecko_bindings::structs::ServoBundledURI;"#) + .raw_line(r#"use gecko_bindings::structs::ServoElementSnapshot;"#) + .raw_line(r#"use gecko_bindings::structs::SheetParsingMode;"#) + .raw_line(r#"use gecko_bindings::structs::StyleBasicShape;"#) + .raw_line(r#"use gecko_bindings::structs::StyleBasicShapeType;"#) + .raw_line(r#"use gecko_bindings::structs::StyleShapeSource;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSFontFaceRule;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSKeyword;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSPropertyID;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSShadowArray;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSUnit;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSValue;"#) + .raw_line(r#"use gecko_bindings::structs::nsCSSValueSharedList;"#) + .raw_line(r#"use gecko_bindings::structs::nsChangeHint;"#) + .raw_line(r#"use gecko_bindings::structs::nsCursorImage;"#) + .raw_line(r#"use gecko_bindings::structs::nsFont;"#) + .raw_line(r#"use gecko_bindings::structs::nsIAtom;"#) + .raw_line(r#"use gecko_bindings::structs::nsMediaFeature;"#) + .raw_line(r#"use gecko_bindings::structs::nsRestyleHint;"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleBackground;"#) + .raw_line(r#"unsafe impl Send for nsStyleBackground {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleBackground {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleBorder;"#) + .raw_line(r#"unsafe impl Send for nsStyleBorder {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleBorder {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleColor;"#) + .raw_line(r#"unsafe impl Send for nsStyleColor {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleColor {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleColumn;"#) + .raw_line(r#"unsafe impl Send for nsStyleColumn {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleColumn {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleContent;"#) + .raw_line(r#"unsafe impl Send for nsStyleContent {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleContent {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleContentData;"#) + .raw_line(r#"unsafe impl Send for nsStyleContentData {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleContentData {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleContentType;"#) + .raw_line(r#"unsafe impl Send for nsStyleContentType {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleContentType {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleContext;"#) + .raw_line(r#"unsafe impl Send for nsStyleContext {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleContext {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleCoord;"#) + .raw_line(r#"unsafe impl Send for nsStyleCoord {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleCoord {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleCoord_Calc;"#) + .raw_line(r#"unsafe impl Send for nsStyleCoord_Calc {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleCoord_Calc {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleCoord_CalcValue;"#) + .raw_line(r#"unsafe impl Send for nsStyleCoord_CalcValue {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleCoord_CalcValue {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleDisplay;"#) + .raw_line(r#"unsafe impl Send for nsStyleDisplay {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleDisplay {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleEffects;"#) + .raw_line(r#"unsafe impl Send for nsStyleEffects {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleEffects {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleFilter;"#) + .raw_line(r#"unsafe impl Send for nsStyleFilter {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleFilter {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleFont;"#) + .raw_line(r#"unsafe impl Send for nsStyleFont {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleFont {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleGradient;"#) + .raw_line(r#"unsafe impl Send for nsStyleGradient {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleGradient {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleGradientStop;"#) + .raw_line(r#"unsafe impl Send for nsStyleGradientStop {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleGradientStop {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleImage;"#) + .raw_line(r#"unsafe impl Send for nsStyleImage {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleImage {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers;"#) + .raw_line(r#"unsafe impl Send for nsStyleImageLayers {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleImageLayers {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers_Layer;"#) + .raw_line(r#"unsafe impl Send for nsStyleImageLayers_Layer {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleImageLayers_Layer {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers_LayerType;"#) + .raw_line(r#"unsafe impl Send for nsStyleImageLayers_LayerType {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleImageLayers_LayerType {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleImageRequest;"#) + .raw_line(r#"unsafe impl Send for nsStyleImageRequest {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleImageRequest {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleList;"#) + .raw_line(r#"unsafe impl Send for nsStyleList {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleList {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleMargin;"#) + .raw_line(r#"unsafe impl Send for nsStyleMargin {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleMargin {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleOutline;"#) + .raw_line(r#"unsafe impl Send for nsStyleOutline {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleOutline {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStylePadding;"#) + .raw_line(r#"unsafe impl Send for nsStylePadding {}"#) + .raw_line(r#"unsafe impl Sync for nsStylePadding {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStylePosition;"#) + .raw_line(r#"unsafe impl Send for nsStylePosition {}"#) + .raw_line(r#"unsafe impl Sync for nsStylePosition {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleQuoteValues;"#) + .raw_line(r#"unsafe impl Send for nsStyleQuoteValues {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleQuoteValues {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleSVG;"#) + .raw_line(r#"unsafe impl Send for nsStyleSVG {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleSVG {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleSVGPaint;"#) + .raw_line(r#"unsafe impl Send for nsStyleSVGPaint {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleSVGPaint {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleSVGReset;"#) + .raw_line(r#"unsafe impl Send for nsStyleSVGReset {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleSVGReset {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleTable;"#) + .raw_line(r#"unsafe impl Send for nsStyleTable {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleTable {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleTableBorder;"#) + .raw_line(r#"unsafe impl Send for nsStyleTableBorder {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleTableBorder {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleText;"#) + .raw_line(r#"unsafe impl Send for nsStyleText {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleText {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleTextReset;"#) + .raw_line(r#"unsafe impl Send for nsStyleTextReset {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleTextReset {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleUIReset;"#) + .raw_line(r#"unsafe impl Send for nsStyleUIReset {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleUIReset {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleUnion;"#) + .raw_line(r#"unsafe impl Send for nsStyleUnion {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleUnion {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleUnit;"#) + .raw_line(r#"unsafe impl Send for nsStyleUnit {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleUnit {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleUserInterface;"#) + .raw_line(r#"unsafe impl Send for nsStyleUserInterface {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleUserInterface {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleVariables;"#) + .raw_line(r#"unsafe impl Send for nsStyleVariables {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleVariables {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleVisibility;"#) + .raw_line(r#"unsafe impl Send for nsStyleVisibility {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleVisibility {}"#) + .raw_line(r#"use gecko_bindings::structs::nsStyleXUL;"#) + .raw_line(r#"unsafe impl Send for nsStyleXUL {}"#) + .raw_line(r#"unsafe impl Sync for nsStyleXUL {}"#) + .raw_line(r#"use gecko_bindings::structs::nsTimingFunction;"#) + .raw_line(r#"use gecko_bindings::structs::nscolor;"#) + .raw_line(r#"use gecko_bindings::structs::nscoord;"#) + .raw_line(r#"use gecko_bindings::structs::nsresult;"#) + .raw_line(r#"use gecko_bindings::structs::Loader;"#) + .raw_line(r#"use gecko_bindings::structs::ServoStyleSheet;"#) + .raw_line(r#"use gecko_bindings::structs::EffectCompositor_CascadeLevel;"#) + .raw_line(r#"use gecko_bindings::structs::UpdateAnimationsTasks;"#) + .raw_line(r#"pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray;"#) + .raw_line(r#"pub type ServoCssRulesStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;"#) + .raw_line(r#"pub type ServoCssRulesBorrowedOrNull<'a> = Option<&'a ServoCssRules>;"#) + .raw_line(r#"enum ServoCssRulesVoid { }"#) + .raw_line(r#"pub struct ServoCssRules(ServoCssRulesVoid);"#) + .raw_line(r#"pub type RawServoStyleSheetStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoStyleSheetBorrowed<'a> = &'a RawServoStyleSheet;"#) + .raw_line(r#"pub type RawServoStyleSheetBorrowedOrNull<'a> = Option<&'a RawServoStyleSheet>;"#) + .raw_line(r#"enum RawServoStyleSheetVoid { }"#) + .raw_line(r#"pub struct RawServoStyleSheet(RawServoStyleSheetVoid);"#) + .raw_line(r#"pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;"#) + .raw_line(r#"pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;"#) + .raw_line(r#"enum ServoComputedValuesVoid { }"#) + .raw_line(r#"pub struct ServoComputedValues(ServoComputedValuesVoid);"#) + .raw_line(r#"pub type RawServoDeclarationBlockStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoDeclarationBlockBorrowed<'a> = &'a RawServoDeclarationBlock;"#) + .raw_line(r#"pub type RawServoDeclarationBlockBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlock>;"#) + .raw_line(r#"pub type RawServoStyleRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoStyleRuleBorrowed<'a> = &'a RawServoStyleRule;"#) + .raw_line(r#"pub type RawServoStyleRuleBorrowedOrNull<'a> = Option<&'a RawServoStyleRule>;"#) + .raw_line(r#"enum RawServoStyleRuleVoid { }"#) + .raw_line(r#"pub struct RawServoStyleRule(RawServoStyleRuleVoid);"#) + .raw_line(r#"pub type RawServoImportRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoImportRuleBorrowed<'a> = &'a RawServoImportRule;"#) + .raw_line(r#"pub type RawServoImportRuleBorrowedOrNull<'a> = Option<&'a RawServoImportRule>;"#) + .raw_line(r#"enum RawServoImportRuleVoid { }"#) + .raw_line(r#"pub struct RawServoImportRule(RawServoImportRuleVoid);"#) + .raw_line(r#"pub type RawServoAnimationValueStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoAnimationValueBorrowed<'a> = &'a RawServoAnimationValue;"#) + .raw_line(r#"pub type RawServoAnimationValueBorrowedOrNull<'a> = Option<&'a RawServoAnimationValue>;"#) + .raw_line(r#"pub type RawServoAnimationValueMapStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoAnimationValueMapBorrowed<'a> = &'a RawServoAnimationValueMap;"#) + .raw_line(r#"pub type RawServoAnimationValueMapBorrowedOrNull<'a> = Option<&'a RawServoAnimationValueMap>;"#) + .raw_line(r#"pub type RawServoMediaListStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoMediaListBorrowed<'a> = &'a RawServoMediaList;"#) + .raw_line(r#"pub type RawServoMediaListBorrowedOrNull<'a> = Option<&'a RawServoMediaList>;"#) + .raw_line(r#"enum RawServoMediaListVoid { }"#) + .raw_line(r#"pub struct RawServoMediaList(RawServoMediaListVoid);"#) + .raw_line(r#"pub type RawServoMediaRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoMediaRuleBorrowed<'a> = &'a RawServoMediaRule;"#) + .raw_line(r#"pub type RawServoMediaRuleBorrowedOrNull<'a> = Option<&'a RawServoMediaRule>;"#) + .raw_line(r#"enum RawServoMediaRuleVoid { }"#) + .raw_line(r#"pub struct RawServoMediaRule(RawServoMediaRuleVoid);"#) + .raw_line(r#"pub type RawServoNamespaceRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) + .raw_line(r#"pub type RawServoNamespaceRuleBorrowed<'a> = &'a RawServoNamespaceRule;"#) + .raw_line(r#"pub type RawServoNamespaceRuleBorrowedOrNull<'a> = Option<&'a RawServoNamespaceRule>;"#) + .raw_line(r#"enum RawServoNamespaceRuleVoid { }"#) + .raw_line(r#"pub struct RawServoNamespaceRule(RawServoNamespaceRuleVoid);"#) + .raw_line(r#"pub type RawServoStyleSetOwned = ::gecko_bindings::sugar::ownership::Owned;"#) + .raw_line(r#"pub type RawServoStyleSetOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) + .raw_line(r#"pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;"#) + .raw_line(r#"pub type RawServoStyleSetBorrowedOrNull<'a> = Option<&'a RawServoStyleSet>;"#) + .raw_line(r#"pub type RawServoStyleSetBorrowedMut<'a> = &'a mut RawServoStyleSet;"#) + .raw_line(r#"pub type RawServoStyleSetBorrowedMutOrNull<'a> = Option<&'a mut RawServoStyleSet>;"#) + .raw_line(r#"enum RawServoStyleSetVoid { }"#) + .raw_line(r#"pub struct RawServoStyleSet(RawServoStyleSetVoid);"#) + .raw_line(r#"pub type StyleChildrenIteratorOwned = ::gecko_bindings::sugar::ownership::Owned;"#) + .raw_line(r#"pub type StyleChildrenIteratorOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) + .raw_line(r#"pub type StyleChildrenIteratorBorrowed<'a> = &'a StyleChildrenIterator;"#) + .raw_line(r#"pub type StyleChildrenIteratorBorrowedOrNull<'a> = Option<&'a StyleChildrenIterator>;"#) + .raw_line(r#"pub type StyleChildrenIteratorBorrowedMut<'a> = &'a mut StyleChildrenIterator;"#) + .raw_line(r#"pub type StyleChildrenIteratorBorrowedMutOrNull<'a> = Option<&'a mut StyleChildrenIterator>;"#) + .raw_line(r#"enum StyleChildrenIteratorVoid { }"#) + .raw_line(r#"pub struct StyleChildrenIterator(StyleChildrenIteratorVoid);"#) + .raw_line(r#"pub type ServoElementSnapshotOwned = ::gecko_bindings::sugar::ownership::Owned;"#) + .raw_line(r#"pub type ServoElementSnapshotOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) + .raw_line(r#"pub type ServoElementSnapshotBorrowed<'a> = &'a ServoElementSnapshot;"#) + .raw_line(r#"pub type ServoElementSnapshotBorrowedOrNull<'a> = Option<&'a ServoElementSnapshot>;"#) + .raw_line(r#"pub type ServoElementSnapshotBorrowedMut<'a> = &'a mut ServoElementSnapshot;"#) + .raw_line(r#"pub type ServoElementSnapshotBorrowedMutOrNull<'a> = Option<&'a mut ServoElementSnapshot>;"#) + .raw_line(r#"pub type RawGeckoNodeBorrowed<'a> = &'a RawGeckoNode;"#) + .raw_line(r#"pub type RawGeckoNodeBorrowedOrNull<'a> = Option<&'a RawGeckoNode>;"#) + .raw_line(r#"pub type RawGeckoElementBorrowed<'a> = &'a RawGeckoElement;"#) + .raw_line(r#"pub type RawGeckoElementBorrowedOrNull<'a> = Option<&'a RawGeckoElement>;"#) + .raw_line(r#"pub type RawGeckoDocumentBorrowed<'a> = &'a RawGeckoDocument;"#) + .raw_line(r#"pub type RawGeckoDocumentBorrowedOrNull<'a> = Option<&'a RawGeckoDocument>;"#) + .raw_line(r#"pub type RawServoDeclarationBlockStrongBorrowed<'a> = &'a RawServoDeclarationBlockStrong;"#) + .raw_line(r#"pub type RawServoDeclarationBlockStrongBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlockStrong>;"#) + .raw_line(r#"pub type RawGeckoPresContextBorrowed<'a> = &'a RawGeckoPresContext;"#) + .raw_line(r#"pub type RawGeckoPresContextBorrowedOrNull<'a> = Option<&'a RawGeckoPresContext>;"#) + .raw_line(r#"pub type RawGeckoStyleAnimationListBorrowed<'a> = &'a RawGeckoStyleAnimationList;"#) + .raw_line(r#"pub type RawGeckoStyleAnimationListBorrowedOrNull<'a> = Option<&'a RawGeckoStyleAnimationList>;"#) + .raw_line(r#"pub type nsCSSValueBorrowed<'a> = &'a nsCSSValue;"#) + .raw_line(r#"pub type nsCSSValueBorrowedOrNull<'a> = Option<&'a nsCSSValue>;"#) + .raw_line(r#"pub type nsCSSValueBorrowedMut<'a> = &'a mut nsCSSValue;"#) + .raw_line(r#"pub type nsCSSValueBorrowedMutOrNull<'a> = Option<&'a mut nsCSSValue>;"#) + .raw_line(r#"pub type nsTimingFunctionBorrowed<'a> = &'a nsTimingFunction;"#) + .raw_line(r#"pub type nsTimingFunctionBorrowedOrNull<'a> = Option<&'a nsTimingFunction>;"#) + .raw_line(r#"pub type nsTimingFunctionBorrowedMut<'a> = &'a mut nsTimingFunction;"#) + .raw_line(r#"pub type nsTimingFunctionBorrowedMutOrNull<'a> = Option<&'a mut nsTimingFunction>;"#) + .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowed<'a> = &'a RawGeckoAnimationPropertySegment;"#) + .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationPropertySegment>;"#) + .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedMut<'a> = &'a mut RawGeckoAnimationPropertySegment;"#) + .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationPropertySegment>;"#) + .raw_line(r#"pub type RawGeckoAnimationValueListBorrowed<'a> = &'a RawGeckoAnimationValueList;"#) + .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationValueList>;"#) + .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedMut<'a> = &'a mut RawGeckoAnimationValueList;"#) + .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationValueList>;"#) + .raw_line(r#"pub type RawGeckoComputedTimingBorrowed<'a> = &'a RawGeckoComputedTiming;"#) + .raw_line(r#"pub type RawGeckoComputedTimingBorrowedOrNull<'a> = Option<&'a RawGeckoComputedTiming>;"#) + .raw_line(r#"pub type RawGeckoComputedTimingBorrowedMut<'a> = &'a mut RawGeckoComputedTiming;"#) + .raw_line(r#"pub type RawGeckoComputedTimingBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoComputedTiming>;"#) + .raw_line(r#"pub type RawGeckoKeyframeListBorrowed<'a> = &'a RawGeckoKeyframeList;"#) + .raw_line(r#"pub type RawGeckoKeyframeListBorrowedOrNull<'a> = Option<&'a RawGeckoKeyframeList>;"#) + .raw_line(r#"pub type RawGeckoKeyframeListBorrowedMut<'a> = &'a mut RawGeckoKeyframeList;"#) + .raw_line(r#"pub type RawGeckoKeyframeListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoKeyframeList>;"#) + .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowed<'a> = &'a RawGeckoComputedKeyframeValuesList;"#) + .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedOrNull<'a> = Option<&'a RawGeckoComputedKeyframeValuesList>;"#) + .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedMut<'a> = &'a mut RawGeckoComputedKeyframeValuesList;"#) + .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoComputedKeyframeValuesList>;"#) + .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowed<'a> = &'a RawGeckoFontFaceRuleList;"#) + .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedOrNull<'a> = Option<&'a RawGeckoFontFaceRuleList>;"#) + .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedMut<'a> = &'a mut RawGeckoFontFaceRuleList;"#) + .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoFontFaceRuleList>;"#) + .clang_arg("-x") + .clang_arg("c++") + .clang_arg("-std=c++14") + .clang_arg("-DTRACING=1") + .clang_arg("-DIMPL_LIBXUL") + .clang_arg("-DMOZ_STYLO_BINDINGS=1") + .clang_arg("-DMOZILLA_INTERNAL_API") + .clang_arg("-DRUST_BINDGEN") + .clang_arg("-DMOZ_STYLO") + .clang_arg("-DOS_POSIX=1") + .clang_arg("-DOS_LINUX=1") + .generate() + .expect("Should generate stylo bindings"); + + let now = Instant::now(); + + println!(); + println!(); + println!( + "Generated Stylo bindings in: {:?}", + now.duration_since(then) + ); + println!(); + println!(); + + // panic!("Uncomment this line to get timing logs"); +} diff --git a/tests/test-one.sh b/bindgen-tests/tests/test-one.sh similarity index 87% rename from tests/test-one.sh rename to bindgen-tests/tests/test-one.sh index 91da55b1a5..5ab6e9a468 100755 --- a/tests/test-one.sh +++ b/bindgen-tests/tests/test-one.sh @@ -45,19 +45,18 @@ TEST_BINDINGS_BINARY=$(mktemp -t bindings.XXXXXX) FLAGS="$(grep "// bindgen-flags: " "$TEST" || echo)" FLAGS="${FLAGS/\/\/ bindgen\-flags:/}" # Prepend the default flags added in test.rs's `create_bindgen_builder`. -FLAGS="--rustfmt-bindings --with-derive-default --raw-line '' --raw-line '#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]' --raw-line '' $FLAGS" +FLAGS="--with-derive-default --raw-line '' --raw-line '#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]' --raw-line '' $FLAGS" -eval ./target/debug/bindgen \ +eval ../target/debug/bindgen \ "\"$TEST\"" \ --emit-ir \ --emit-ir-graphviz ir.dot \ --emit-clang-ast \ + --formatter prettyplease \ -o "\"$BINDINGS\"" \ $FLAGS -rustup run nightly rustfmt "$BINDINGS" || true - dot -Tpng ir.dot -o ir.png echo @@ -80,8 +79,6 @@ EXPECTED=${TEST/headers/expectations\/tests} EXPECTED=${EXPECTED/.hpp/.rs} EXPECTED=${EXPECTED/.h/.rs} -rustup run nightly rustfmt "$EXPECTED" || true - # Don't exit early if there is a diff. diff -U8 "$EXPECTED" "$BINDINGS" || true diff --git a/bindgen-tests/tests/tests.rs b/bindgen-tests/tests/tests.rs new file mode 100644 index 0000000000..6e3c358d3e --- /dev/null +++ b/bindgen-tests/tests/tests.rs @@ -0,0 +1,776 @@ +use bindgen::{clang_version, Builder}; +use owo_colors::{OwoColorize, Style}; +use similar::{ChangeTag, TextDiff}; +use std::env; +use std::fmt; +use std::fs; +use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write}; +use std::path::{Path, PathBuf}; + +use bindgen::builder_from_flags; + +mod parse_callbacks; + +// Format the given source string. It can fail if the source string does not contain syntactically +// valid Rust. +fn format_code>(source: S) -> syn::Result { + use prettyplease::unparse; + use syn::{parse_str, File}; + + let file = parse_str::(source.as_ref())?; + Ok(unparse(&file)) +} + +fn should_overwrite_expected() -> bool { + if let Some(var) = env::var_os("BINDGEN_OVERWRITE_EXPECTED") { + if var == "1" { + return true; + } + assert!( + var == "0" || var.is_empty(), + "Invalid value of BINDGEN_OVERWRITE_EXPECTED" + ); + } + false +} + +fn error_diff_mismatch( + actual: &str, + expected: &str, + header: Option<&Path>, + filename: &Path, +) -> Result<(), Error> { + println!("diff expected generated"); + println!("--- expected: {}", filename.display()); + if let Some(header) = header { + println!("+++ generated from: {}", header.display()); + } + + show_diff(expected, actual); + + if should_overwrite_expected() { + // Overwrite the expectation with actual output. + let mut expectation_file = fs::File::create(filename)?; + expectation_file.write_all(actual.as_bytes())?; + } + + if let Some(var) = env::var_os("BINDGEN_TESTS_DIFFTOOL") { + //usecase: var = "meld" -> You can hand check differences + let Some(std::path::Component::Normal(name)) = + filename.components().next_back() + else { + panic!("Why is the header variable so weird?") + }; + let actual_result_path = + PathBuf::from(env::var("OUT_DIR").unwrap()).join(name); + let mut actual_result_file = fs::File::create(&actual_result_path)?; + actual_result_file.write_all(actual.as_bytes())?; + std::process::Command::new(var) + .args([filename, &actual_result_path]) + .output()?; + } + + Err(Error::new(ErrorKind::Other, "Header and binding differ! Run with BINDGEN_OVERWRITE_EXPECTED=1 in the environment to automatically overwrite the expectation or with BINDGEN_TESTS_DIFFTOOL=meld to do this manually.")) +} + +struct Line(Option); + +impl fmt::Display for Line { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + None => write!(f, " "), + Some(idx) => write!(f, "{:<4}", idx + 1), + } + } +} + +fn show_diff(old: &str, new: &str) { + let diff = TextDiff::from_lines(old, new); + for (count, group) in diff.grouped_ops(3).iter().enumerate() { + if count > 0 { + let message = format!("(chunk {count}/n)"); + println!("{}", message.cyan().dimmed()); + } + for diff_op in group { + for change in diff.iter_inline_changes(diff_op) { + let (sign, color) = match change.tag() { + ChangeTag::Delete => ("-", Style::new().red()), + ChangeTag::Insert => ("+", Style::new().green()), + ChangeTag::Equal => (" ", Style::new()), + }; + print!( + "{}{}| {}", + Line(change.old_index()).style(color).dimmed(), + Line(change.new_index()).style(color).dimmed(), + sign.style(color).bold(), + ); + for (emphasized, text) in change.iter_strings_lossy() { + if emphasized { + print!("{}", text.style(color).underline()); + } else { + print!("{}", text.style(color)); + } + } + if change.missing_newline() { + println!(); + } + } + } + } +} + +fn compare_generated_header( + header: &Path, + builder: BuilderState, + check_roundtrip: bool, +) -> Result<(), Error> { + let file_name = header.file_name().ok_or_else(|| { + Error::new(ErrorKind::Other, "compare_generated_header expects a file") + })?; + + let mut expectation = PathBuf::from(header); + expectation.pop(); + expectation.pop(); + expectation.push("expectations"); + expectation.push("tests"); + + let mut looked_at = vec![]; + let mut expectation_file; + + // Try more specific expectations first. + { + let mut expectation = expectation.clone(); + + if cfg!(feature = "__testing_only_libclang_16") { + expectation.push("libclang-16"); + } else if cfg!(feature = "__testing_only_libclang_9") { + expectation.push("libclang-9"); + } else { + match clang_version().parsed { + None => expectation.push("libclang-16"), + Some(version) => { + let (maj, min) = version; + let version_str = if maj >= 16 { + "16".to_owned() + } else if maj >= 9 { + "9".to_owned() + } else { + format!("{maj}.{min}") + }; + expectation.push(format!("libclang-{version_str}")); + } + } + } + + expectation.push(file_name); + expectation.set_extension("rs"); + expectation_file = fs::File::open(&expectation).ok(); + looked_at.push(expectation); + } + + // Try the default path otherwise. + if expectation_file.is_none() { + expectation.push(file_name); + expectation.set_extension("rs"); + expectation_file = fs::File::open(&expectation).ok(); + looked_at.push(expectation.clone()); + } + + let mut expected = String::new(); + match expectation_file { + Some(f) => { + BufReader::new(f).read_to_string(&mut expected)?; + } + None => panic!( + "missing test expectation file and/or '__testing_only_libclang_$VERSION' \ + feature for header '{}'; looking for expectation file at '{looked_at:?}'", + header.display(), + ), + } + + let (builder, roundtrip_builder) = builder.into_builder(check_roundtrip)?; + + // We skip the generate() error here so we get a full diff below + let actual = match builder.generate() { + Ok(bindings) => format_code(bindings.to_string()).map_err(|err| { + Error::new( + ErrorKind::Other, + format!("Cannot parse the generated bindings: {err}"), + ) + })?, + Err(_) => "/* error generating bindings */\n".into(), + }; + + if actual.is_empty() { + return Err(Error::new( + ErrorKind::Other, + "Something's gone really wrong!", + )); + } + if actual != expected { + return error_diff_mismatch( + &actual, + &expected, + Some(header), + looked_at.last().unwrap(), + ); + } + + if let Some(roundtrip_builder) = roundtrip_builder { + if let Err(e) = + compare_generated_header(header, roundtrip_builder, false) + { + return Err(Error::new(ErrorKind::Other, format!("Checking CLI flags roundtrip errored! You probably need to fix Builder::command_line_flags. {e}"))); + } + } + + Ok(()) +} + +fn builder() -> Builder { + #[cfg(feature = "logging")] + let _ = env_logger::try_init(); + + bindgen::builder().disable_header_comment() +} + +struct BuilderState { + builder: Builder, + parse_callbacks: Option, +} + +impl BuilderState { + fn into_builder( + self, + with_roundtrip_builder: bool, + ) -> Result<(Builder, Option), Error> { + let roundtrip_builder = if with_roundtrip_builder { + let mut flags = self.builder.command_line_flags(); + flags.insert(0, "bindgen".into()); + let mut builder = builder_from_flags(flags.into_iter())?.0; + if let Some(ref parse_cb) = self.parse_callbacks { + builder = + builder.parse_callbacks(parse_callbacks::lookup(parse_cb)); + } + Some(BuilderState { + builder, + parse_callbacks: self.parse_callbacks, + }) + } else { + None + }; + Ok((self.builder, roundtrip_builder)) + } +} + +fn create_bindgen_builder(header: &Path) -> Result { + #[cfg(feature = "logging")] + let _ = env_logger::try_init(); + + let source = fs::File::open(header)?; + let reader = BufReader::new(source); + + // Scoop up bindgen-flags from test header + let mut flags = Vec::with_capacity(2); + let mut parse_callbacks = None; + + for line in reader.lines() { + let line = line?; + if !line.starts_with("// bindgen") { + continue; + } + + if line.contains("bindgen-flags: ") { + let extra_flags = line + .split("bindgen-flags: ") + .last() + .and_then(shlex::split) + .unwrap(); + flags.extend(extra_flags); + } else if line.contains("bindgen-osx-only") { + let prepend_flags = ["--raw-line", "#![cfg(target_os=\"macos\")]"]; + flags = prepend_flags + .iter() + .map(ToString::to_string) + .chain(flags) + .collect(); + } else if line.contains("bindgen-parse-callbacks: ") { + let parse_cb = + line.split("bindgen-parse-callbacks: ").last().unwrap(); + parse_callbacks = Some(parse_cb.to_owned()); + } + } + + // Different platforms have various different conventions like struct padding, mangling, etc. + // We make the default target as x86_64-unknown-linux + if flags.iter().all(|flag| !flag.starts_with("--target=")) { + if !flags.iter().any(|flag| flag == "--") { + flags.push("--".into()); + } + flags.push("--target=x86_64-unknown-linux".into()); + } + + // Fool builder_from_flags() into believing it has real env::args_os... + // - add "bindgen" as executable name 0th element + // - add header filename as 1st element + // - prepend raw lines so they're in the right order for expected output + // - append the test header's bindgen flags + let header_str = header.to_str().ok_or_else(|| { + Error::new(ErrorKind::Other, "Invalid header file name") + })?; + + let prepend = [ + "bindgen", + // We format in `compare_generated_header` ourselves to have a little + // more control. + "--formatter=none", + "--with-derive-default", + "--disable-header-comment", + "--vtable-generation", + header_str, + "--raw-line", + "", + "--raw-line", + "#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]", + "--raw-line", + "", + ]; + + let args = prepend.iter().map(ToString::to_string).chain(flags); + + let mut builder = builder_from_flags(args)?.0; + if let Some(ref parse_cb) = parse_callbacks { + builder = builder.parse_callbacks(parse_callbacks::lookup(parse_cb)); + } + Ok(BuilderState { + builder, + parse_callbacks, + }) +} + +macro_rules! test_header { + ($function:ident, $header:expr) => { + #[test] + fn $function() { + let header = PathBuf::from($header); + let result = create_bindgen_builder(&header).and_then(|builder| { + let check_roundtrip = + env::var_os("BINDGEN_DISABLE_ROUNDTRIP_TEST").is_none(); + compare_generated_header(&header, builder, check_roundtrip) + }); + + if let Err(err) = result { + panic!("{err}"); + } + } + }; +} + +// This file is generated by build.rs +include!(concat!(env!("OUT_DIR"), "/tests.rs")); + +#[test] +#[cfg_attr(target_os = "windows", ignore)] +fn test_clang_env_args() { + env::set_var( + "BINDGEN_EXTRA_CLANG_ARGS", + "-D_ENV_ONE=1 -D_ENV_TWO=\"2 -DNOT_THREE=1\"", + ); + let actual = builder() + .disable_header_comment() + .header_contents( + "test.hpp", + "#ifdef _ENV_ONE\nextern const int x[] = { 42 };\n#endif\n\ + #ifdef _ENV_TWO\nextern const int y[] = { 42 };\n#endif\n\ + #if defined NOT_THREE && NOT_THREE == 1\nextern const int z[] = { 42 };\n#endif\n", + ) + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected = format_code( + "unsafe extern \"C\" { + pub static x: [::std::os::raw::c_int; 1usize]; +} +unsafe extern \"C\" { + pub static y: [::std::os::raw::c_int; 1usize]; +} +", + ) + .unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn test_header_contents() { + let actual = builder() + .disable_header_comment() + .header_contents("test.h", "int foo(const char* a);") + .clang_arg("--target=x86_64-unknown-linux") + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected = format_code( + "unsafe extern \"C\" { + pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} +", + ) + .unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn test_multiple_header_calls_in_builder() { + let actual = builder() + .header(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/headers/func_ptr.h" + )) + .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/char.h")) + .clang_arg("--target=x86_64-unknown-linux") + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected_filename = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs" + ); + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs" + )); + let expected = format_code(expected).unwrap(); + + if actual != expected { + println!("Generated bindings differ from expected!"); + error_diff_mismatch( + &actual, + &expected, + None, + Path::new(expected_filename), + ) + .unwrap(); + } +} + +#[test] +fn test_headers_call_in_builder() { + let actual = builder() + .headers([ + concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/func_ptr.h"), + concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/char.h"), + ]) + .clang_arg("--target=x86_64-unknown-linux") + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected_filename = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs" + ); + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs" + )); + let expected = format_code(expected).unwrap(); + + if actual != expected { + println!("Generated bindings differ from expected!"); + error_diff_mismatch( + &actual, + &expected, + None, + Path::new(expected_filename), + ) + .unwrap(); + } +} + +#[test] +fn test_multiple_header_contents() { + let actual = builder() + .header_contents("test.h", "int foo(const char* a);") + .header_contents("test2.h", "float foo2(const char* b);") + .clang_arg("--target=x86_64-unknown-linux") + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected = format_code( + "unsafe extern \"C\" { + pub fn foo2(b: *const ::std::os::raw::c_char) -> f32; +} +unsafe extern \"C\" { + pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} +", + ) + .unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn test_mixed_header_and_header_contents() { + let actual = builder() + .header(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/headers/func_ptr.h" + )) + .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/char.h")) + .header_contents("test.h", "int bar(const char* a);") + .header_contents("test2.h", "float bar2(const char* b);") + .clang_arg("--target=x86_64-unknown-linux") + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let expected_filename = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_mixed_header_and_header_contents.rs" + ); + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_mixed_header_and_header_contents.rs" + )); + let expected = format_code(expected).unwrap(); + if expected != actual { + error_diff_mismatch( + &actual, + &expected, + None, + Path::new(expected_filename), + ) + .unwrap(); + } +} + +#[test] +fn test_macro_fallback_non_system_dir() { + let actual = builder() + .header(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/macro_fallback_test_headers/one_header.h" + )) + .header(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/macro_fallback_test_headers/another_header.h" + )) + .clang_macro_fallback() + .clang_arg(format!("-I{}/tests/headers", env!("CARGO_MANIFEST_DIR"))) + .generate() + .unwrap() + .to_string(); + + let actual = format_code(actual).unwrap(); + + let (expected_filename, expected) = if let Some((9, _)) = + clang_version().parsed + { + let expected_filename = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/libclang-9/macro_fallback_non_system_dir.rs", + ); + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/libclang-9/macro_fallback_non_system_dir.rs", + )); + (expected_filename, expected) + } else { + let expected_filename = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_macro_fallback_non_system_dir.rs", + ); + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/expectations/tests/test_macro_fallback_non_system_dir.rs", + )); + (expected_filename, expected) + }; + let expected = format_code(expected).unwrap(); + if expected != actual { + error_diff_mismatch( + &actual, + &expected, + None, + Path::new(expected_filename), + ) + .unwrap(); + } +} + +#[test] +// Doesn't support executing sh file on Windows. +// We may want to implement it in Rust so that we support all systems. +#[cfg(not(target_os = "windows"))] +fn no_system_header_includes() { + use std::process::Command; + assert!(Command::new("../ci/no-includes.sh") + .current_dir(env!("CARGO_MANIFEST_DIR")) + .spawn() + .expect("should spawn ../ci/no-includes.sh OK") + .wait() + .expect("should wait for ../ci/no-includes OK") + .success()); +} + +#[test] +fn emit_depfile() { + let header = PathBuf::from("tests/headers/enum-default-rust.h"); + let expected_depfile = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests") + .join("expectations") + .join("tests") + .join("enum-default-rust.d"); + let observed_depfile = tempfile::NamedTempFile::new().unwrap(); + let mut builder = create_bindgen_builder(&header).unwrap(); + builder.builder = builder.builder.depfile( + "tests/expectations/tests/enum-default-rust.rs", + observed_depfile.path(), + ); + + let check_roundtrip = + env::var_os("BINDGEN_DISABLE_ROUNDTRIP_TEST").is_none(); + let (builder, _roundtrip_builder) = + builder.into_builder(check_roundtrip).unwrap(); + let _bindings = builder.generate().unwrap(); + + let observed = fs::read_to_string(observed_depfile).unwrap(); + let expected = fs::read_to_string(expected_depfile).unwrap(); + assert_eq!(observed.trim(), expected.trim()); +} + +#[test] +fn dump_preprocessed_input() { + let arg_keyword = + concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/arg_keyword.hpp"); + let empty_layout = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/headers/cpp-empty-layout.hpp" + ); + + builder() + .header(arg_keyword) + .header(empty_layout) + .dump_preprocessed_input() + .expect("should dump preprocessed input"); + + fn slurp(p: &str) -> String { + let mut contents = String::new(); + let mut file = fs::File::open(p).unwrap(); + file.read_to_string(&mut contents).unwrap(); + contents + } + + let bindgen_ii = slurp("__bindgen.ii"); + let arg_keyword = slurp(arg_keyword); + let empty_layout = slurp(empty_layout); + + assert!( + bindgen_ii.contains(&arg_keyword), + "arg_keyword.hpp is in the preprocessed file" + ); + assert!( + bindgen_ii.contains(&empty_layout), + "cpp-empty-layout.hpp is in the preprocessed file" + ); +} + +fn build_flags_output_helper(builder: &Builder) { + let mut command_line_flags = builder.command_line_flags(); + command_line_flags.insert(0, "bindgen".to_string()); + + let flags_quoted: Vec = command_line_flags + .iter() + .map(|x| format!("{}", shlex::try_quote(x).unwrap())) + .collect(); + let flags_str = flags_quoted.join(" "); + println!("{flags_str}"); + + let (builder, _output, _verbose) = + builder_from_flags(command_line_flags.into_iter()).unwrap(); + builder.generate().expect("failed to generate bindings"); +} + +#[test] +fn commandline_multiple_headers() { + let bindings = Builder::default() + .header("tests/headers/char.h") + .header("tests/headers/func_ptr.h") + .header("tests/headers/16-byte-alignment.h"); + build_flags_output_helper(&bindings); +} + +#[test] +fn test_wrap_static_fns() { + // This test is for testing diffs of the generated C source and header files + // TODO: If another such feature is added, convert this test into a more generic + // test that looks at `tests/headers/generated` directory. + + // aarch64-linux has a bug, remove custom source when it is solved: + // https://github.com/rust-lang/rust-bindgen/issues/3234 + let wrap_static_fns_c_name = + if cfg!(all(target_arch = "aarch64", target_os = "linux")) { + "wrap_static_fns_aarch64_linux" + } else { + "wrap_static_fns" + }; + + let expect_path = PathBuf::from("tests/expectations/tests/generated") + .join(wrap_static_fns_c_name); + println!("In path is ::: {}", expect_path.display()); + + let generated_path = + PathBuf::from(env::var("OUT_DIR").unwrap()).join("wrap_static_fns"); + println!("Out path is ::: {}", generated_path.display()); + + #[allow(unused_mut)] + let mut builder = Builder::default() + .header("tests/headers/wrap-static-fns.h") + .wrap_static_fns(true) + .wrap_static_fns_path(generated_path.display().to_string()) + .parse_callbacks(Box::new(parse_callbacks::WrapAsVariadicFn)); + + // aarch64-linux has a bug, remove when it is solved: + // https://github.com/rust-lang/rust-bindgen/issues/3234 + #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + { + builder = builder.clang_arg("-DDISABLE_VA"); + } + + builder.generate().expect("Failed to generate bindings"); + + let expected_c = fs::read_to_string(expect_path.with_extension("c")) + .expect("Could not read generated wrap_static_fns.c"); + + let actual_c = fs::read_to_string(generated_path.with_extension("c")) + .expect("Could not read actual wrap_static_fns.c"); + + if expected_c != actual_c { + error_diff_mismatch( + &actual_c, + &expected_c, + None, + &expect_path.with_extension("c"), + ) + .unwrap(); + } +} diff --git a/tests/uses/.gitignore b/bindgen-tests/tests/uses/.gitignore similarity index 100% rename from tests/uses/.gitignore rename to bindgen-tests/tests/uses/.gitignore diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml new file mode 100644 index 0000000000..478574edb3 --- /dev/null +++ b/bindgen/Cargo.toml @@ -0,0 +1,72 @@ +lints.workspace = true + +[package] +authors = [ + "Jyun-Yan You ", + "Emilio Cobos Álvarez ", + "Nick Fitzgerald ", + "The Servo project developers", +] +description = "Automatically generates Rust FFI bindings to C and C++ libraries." +keywords = ["bindings", "ffi", "code-generation"] +categories = ["external-ffi-bindings", "development-tools::ffi"] +license = "BSD-3-Clause" +name = "bindgen" +readme = "../README.md" +repository = "https://github.com/rust-lang/rust-bindgen" +documentation = "https://docs.rs/bindgen" +homepage = "https://rust-lang.github.io/rust-bindgen/" +version = "0.72.0" +build = "build.rs" +rust-version.workspace = true +edition.workspace = true + +[lib] +name = "bindgen" +path = "lib.rs" + +[dependencies] +annotate-snippets = { workspace = true, optional = true } +bitflags.workspace = true +cexpr.workspace = true +clang-sys = { workspace = true, features = ["clang_11_0"] } +clap = { workspace = true, features = ["derive"], optional = true } +clap_complete = { workspace = true, optional = true } +itertools = { workspace = true } +log = { workspace = true, optional = true } +prettyplease = { workspace = true, optional = true, features = ["verbatim"] } +proc-macro2.workspace = true +quote.workspace = true +regex = { workspace = true, features = ["std", "unicode-perl"] } +rustc-hash.workspace = true +shlex.workspace = true +syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] } + +[features] +default = ["logging", "prettyplease", "runtime"] +logging = ["dep:log"] +static = ["clang-sys/static"] +runtime = ["clang-sys/runtime"] +experimental = ["dep:annotate-snippets"] + +## The following features are for internal use and they shouldn't be used if +## you're not hacking on bindgen +# Features used by `bindgen-cli` +__cli = ["dep:clap", "dep:clap_complete"] +# Features used for CI testing +__testing_only_extra_assertions = [] +__testing_only_libclang_9 = [] +__testing_only_libclang_16 = [] + +[package.metadata.docs.rs] +features = ["experimental"] + +[package.metadata.release] +release = true +pre-release-hook = ["../node_modules/doctoc/doctoc.js", "../CHANGELOG.md"] + +# Add version and date to changelog file +[[package.metadata.release.pre-release-replacements]] +file = "../CHANGELOG.md" +search = "# Unreleased" +replace = "# Unreleased\n## Added\n## Changed\n## Removed\n## Fixed\n## Security\n\n# {{version}} ({{date}})" diff --git a/bindgen/LICENSE b/bindgen/LICENSE new file mode 120000 index 0000000000..ea5b60640b --- /dev/null +++ b/bindgen/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/bindgen/build.rs b/bindgen/build.rs new file mode 100644 index 0000000000..4fb2d3075e --- /dev/null +++ b/bindgen/build.rs @@ -0,0 +1,29 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; + +fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + let mut dst = + File::create(Path::new(&out_dir).join("host-target.txt")).unwrap(); + dst.write_all(env::var("TARGET").unwrap().as_bytes()) + .unwrap(); + + // On behalf of clang_sys, rebuild ourselves if important configuration + // variables change, to ensure that bindings get rebuilt if the + // underlying libclang changes. + println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH"); + println!("cargo:rerun-if-env-changed=LIBCLANG_PATH"); + println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH"); + println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS"); + println!( + "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", + env::var("TARGET").unwrap() + ); + println!( + "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", + env::var("TARGET").unwrap().replace('-', "_") + ); +} diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs new file mode 100644 index 0000000000..c8ac9a5e15 --- /dev/null +++ b/bindgen/callbacks.rs @@ -0,0 +1,337 @@ +//! A public API for more fine-grained customization of bindgen behavior. + +pub use crate::ir::analysis::DeriveTrait; +pub use crate::ir::derive::CanDerive as ImplementsTrait; +pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue}; +pub use crate::ir::int::IntKind; +pub use cexpr::token::Kind as TokenKind; +pub use cexpr::token::Token; +use std::fmt; + +/// An enum to allow ignoring parsing of macros. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +pub enum MacroParsingBehavior { + /// Ignore the macro, generating no code for it, or anything that depends on + /// it. + Ignore, + /// The default behavior bindgen would have otherwise. + #[default] + Default, +} + +/// A trait to allow configuring different kinds of types in different +/// situations. +pub trait ParseCallbacks: fmt::Debug { + #[cfg(feature = "__cli")] + #[doc(hidden)] + fn cli_args(&self) -> Vec { + vec![] + } + + /// This function will be run on every macro that is identified. + fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior { + MacroParsingBehavior::Default + } + + /// This function will run for every extern variable and function. The returned value determines + /// the name visible in the bindings. + fn generated_name_override( + &self, + _item_info: ItemInfo<'_>, + ) -> Option { + None + } + + /// This function will run for every extern variable and function. The returned value determines + /// the link name in the bindings. + fn generated_link_name_override( + &self, + _item_info: ItemInfo<'_>, + ) -> Option { + None + } + + /// Modify the contents of a macro + fn modify_macro(&self, _name: &str, _tokens: &mut Vec) {} + + /// The integer kind an integer macro should have, given a name and the + /// value of that macro, or `None` if you want the default to be chosen. + fn int_macro(&self, _name: &str, _value: i64) -> Option { + None + } + + /// This will be run on every string macro. The callback cannot influence the further + /// treatment of the macro, but may use the value to generate additional code or configuration. + fn str_macro(&self, _name: &str, _value: &[u8]) {} + + /// This will be run on every function-like macro. The callback cannot + /// influence the further treatment of the macro, but may use the value to + /// generate additional code or configuration. + /// + /// The first parameter represents the name and argument list (including the + /// parentheses) of the function-like macro. The second parameter represents + /// the expansion of the macro as a sequence of tokens. + fn func_macro(&self, _name: &str, _value: &[&[u8]]) {} + + /// This function should return whether, given an enum variant + /// name, and value, this enum variant will forcibly be a constant. + fn enum_variant_behavior( + &self, + _enum_name: Option<&str>, + _original_variant_name: &str, + _variant_value: EnumVariantValue, + ) -> Option { + None + } + + /// Allows to rename an enum variant, replacing `_original_variant_name`. + fn enum_variant_name( + &self, + _enum_name: Option<&str>, + _original_variant_name: &str, + _variant_value: EnumVariantValue, + ) -> Option { + None + } + + /// Allows to rename an item, replacing `_item_info.name`. + fn item_name(&self, _item_info: ItemInfo) -> Option { + None + } + + /// This will be called on every header filename passed to (`Builder::header`)[`crate::Builder::header`]. + fn header_file(&self, _filename: &str) {} + + /// This will be called on every file inclusion, with the full path of the included file. + fn include_file(&self, _filename: &str) {} + + /// This will be called every time `bindgen` reads an environment variable whether it has any + /// content or not. + fn read_env_var(&self, _key: &str) {} + + /// This will be called to determine whether a particular blocklisted type + /// implements a trait or not. This will be used to implement traits on + /// other types containing the blocklisted type. + /// + /// * `None`: use the default behavior + /// * `Some(ImplementsTrait::Yes)`: `_name` implements `_derive_trait` + /// * `Some(ImplementsTrait::Manually)`: any type including `_name` can't + /// derive `_derive_trait` but can implemented it manually + /// * `Some(ImplementsTrait::No)`: `_name` doesn't implement `_derive_trait` + fn blocklisted_type_implements_trait( + &self, + _name: &str, + _derive_trait: DeriveTrait, + ) -> Option { + None + } + + /// Provide a list of custom derive attributes. + /// + /// If no additional attributes are wanted, this function should return an + /// empty `Vec`. + fn add_derives(&self, _info: &DeriveInfo<'_>) -> Vec { + vec![] + } + + /// Provide a list of custom attributes. + /// + /// If no additional attributes are wanted, this function should return an + /// empty `Vec`. + fn add_attributes(&self, _info: &AttributeInfo<'_>) -> Vec { + vec![] + } + + /// Process a source code comment. + fn process_comment(&self, _comment: &str) -> Option { + None + } + + /// Potentially override the visibility of a composite type field. + /// + /// Caution: This allows overriding standard C++ visibility inferred by + /// `respect_cxx_access_specs`. + fn field_visibility( + &self, + _info: FieldInfo<'_>, + ) -> Option { + None + } + + /// Process a function name that as exactly one `va_list` argument + /// to be wrapped as a variadic function with the wrapped static function + /// feature. + /// + /// The returned string is new function name. + #[cfg(feature = "experimental")] + fn wrap_as_variadic_fn(&self, _name: &str) -> Option { + None + } + + /// This will get called everytime an item (currently struct, union, and alias) is found with some information about it + fn new_item_found( + &self, + _id: DiscoveredItemId, + _item: DiscoveredItem, + _source_location: Option<&SourceLocation>, + ) { + } + + // TODO add callback for ResolvedTypeRef +} + +/// An identifier for a discovered item. Used to identify an aliased type (see [`DiscoveredItem::Alias`]) +#[derive(Ord, PartialOrd, PartialEq, Eq, Hash, Debug, Clone, Copy)] +pub struct DiscoveredItemId(usize); + +impl DiscoveredItemId { + /// Constructor + pub fn new(value: usize) -> Self { + Self(value) + } +} + +/// Struct passed to [`ParseCallbacks::new_item_found`] containing information about discovered +/// items (struct, union, and alias) +#[derive(Debug, Hash, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum DiscoveredItem { + /// Represents a struct with its original name in C and its generated binding name + Struct { + /// The original name (learnt from C) of the structure + /// Can be None if the union is anonymous. + original_name: Option, + + /// The name of the generated binding + final_name: String, + }, + + /// Represents a union with its original name in C and its generated binding name + Union { + /// The original name (learnt from C) of the structure. + /// Can be None if the union is anonymous. + original_name: Option, + + /// The name of the generated binding + final_name: String, + }, + + /// Represents an alias like a typedef + /// ```c + /// typedef struct MyStruct { + /// ... + /// } StructAlias; + /// ``` + /// Here, the name of the alias is `StructAlias` and it's an alias for `MyStruct` + Alias { + /// The name of the alias in C (`StructAlias`) + alias_name: String, + + /// The identifier of the discovered type + alias_for: DiscoveredItemId, + }, + + /// Represents an enum. + Enum { + /// The final name of the generated binding + final_name: String, + }, + + /// A function or method. + Function { + /// The final name used. + final_name: String, + }, + + /// A method. + Method { + /// The final name used. + final_name: String, + + /// Type to which this method belongs. + parent: DiscoveredItemId, + }, // modules, etc. +} + +/// Relevant information about a type to which new derive attributes will be added using +/// [`ParseCallbacks::add_derives`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub struct DeriveInfo<'a> { + /// The name of the type. + pub name: &'a str, + /// The kind of the type. + pub kind: TypeKind, +} + +/// Relevant information about a type to which new attributes will be added using +/// [`ParseCallbacks::add_attributes`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub struct AttributeInfo<'a> { + /// The name of the type. + pub name: &'a str, + /// The kind of the type. + pub kind: TypeKind, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +/// The kind of the current type. +pub enum TypeKind { + /// The type is a Rust `struct`. + Struct, + /// The type is a Rust `enum`. + Enum, + /// The type is a Rust `union`. + Union, +} + +/// A struct providing information about the item being passed to [`ParseCallbacks::generated_name_override`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub struct ItemInfo<'a> { + /// The name of the item + pub name: &'a str, + /// The kind of item + pub kind: ItemKind, +} + +/// An enum indicating the kind of item for an `ItemInfo`. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum ItemKind { + /// A module + Module, + /// A type + Type, + /// A Function + Function, + /// A Variable + Var, +} + +/// Relevant information about a field for which visibility can be determined using +/// [`ParseCallbacks::field_visibility`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub struct FieldInfo<'a> { + /// The name of the type. + pub type_name: &'a str, + /// The name of the field. + pub field_name: &'a str, + /// The name of the type of the field. + pub field_type_name: Option<&'a str>, +} + +/// Location in the source code. Roughly equivalent to the same type +/// within `clang_sys`. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SourceLocation { + /// Line number. + pub line: usize, + /// Column number within line. + pub col: usize, + /// Byte offset within file. + pub byte_offset: usize, + /// Filename, if known. + pub file_name: Option, +} diff --git a/bindgen/clang.rs b/bindgen/clang.rs new file mode 100644 index 0000000000..9e614da9f8 --- /dev/null +++ b/bindgen/clang.rs @@ -0,0 +1,2449 @@ +//! A higher level Clang API built on top of the generated bindings in the +//! `clang_sys` module. + +#![allow(non_upper_case_globals, dead_code)] +#![deny(clippy::missing_docs_in_private_items)] + +use crate::ir::context::BindgenContext; +use clang_sys::*; +use std::cmp; + +use std::ffi::{CStr, CString}; +use std::fmt; +use std::fs::OpenOptions; +use std::hash::Hash; +use std::hash::Hasher; +use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong}; +use std::sync::OnceLock; +use std::{mem, ptr, slice}; + +/// Type representing a clang attribute. +/// +/// Values of this type can be used to check for different attributes using the `has_attrs` +/// function. +pub(crate) struct Attribute { + name: &'static [u8], + kind: Option, + token_kind: CXTokenKind, +} + +impl Attribute { + /// A `warn_unused_result` attribute. + pub(crate) const MUST_USE: Self = Self { + name: b"warn_unused_result", + // FIXME(emilio): clang-sys doesn't expose `CXCursor_WarnUnusedResultAttr` (from clang 9). + kind: Some(440), + token_kind: CXToken_Identifier, + }; + + /// A `_Noreturn` attribute. + pub(crate) const NO_RETURN: Self = Self { + name: b"_Noreturn", + kind: None, + token_kind: CXToken_Keyword, + }; + + /// A `[[noreturn]]` attribute. + pub(crate) const NO_RETURN_CPP: Self = Self { + name: b"noreturn", + kind: None, + token_kind: CXToken_Identifier, + }; +} + +/// A cursor into the Clang AST, pointing to an AST node. +/// +/// We call the AST node pointed to by the cursor the cursor's "referent". +#[derive(Copy, Clone)] +pub(crate) struct Cursor { + x: CXCursor, +} + +impl fmt::Debug for Cursor { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!( + fmt, + "Cursor({} kind: {}, loc: {}, usr: {:?})", + self.spelling(), + kind_to_str(self.kind()), + self.location(), + self.usr() + ) + } +} + +impl Cursor { + /// Get the Unified Symbol Resolution for this cursor's referent, if + /// available. + /// + /// The USR can be used to compare entities across translation units. + pub(crate) fn usr(&self) -> Option { + let s = unsafe { cxstring_into_string(clang_getCursorUSR(self.x)) }; + if s.is_empty() { + None + } else { + Some(s) + } + } + + /// Is this cursor's referent a declaration? + pub(crate) fn is_declaration(&self) -> bool { + unsafe { clang_isDeclaration(self.kind()) != 0 } + } + + /// Is this cursor's referent an anonymous record or so? + pub(crate) fn is_anonymous(&self) -> bool { + unsafe { clang_Cursor_isAnonymous(self.x) != 0 } + } + + /// Get this cursor's referent's spelling. + pub(crate) fn spelling(&self) -> String { + unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) } + } + + /// Get this cursor's referent's display name. + /// + /// This is not necessarily a valid identifier. It includes extra + /// information, such as parameters for a function, etc. + pub(crate) fn display_name(&self) -> String { + unsafe { cxstring_into_string(clang_getCursorDisplayName(self.x)) } + } + + /// Get the mangled name of this cursor's referent. + pub(crate) fn mangling(&self) -> String { + unsafe { cxstring_into_string(clang_Cursor_getMangling(self.x)) } + } + + /// Gets the C++ manglings for this cursor, or an error if the manglings + /// are not available. + pub(crate) fn cxx_manglings(&self) -> Result, ()> { + use clang_sys::*; + unsafe { + let manglings = clang_Cursor_getCXXManglings(self.x); + if manglings.is_null() { + return Err(()); + } + let count = (*manglings).Count as usize; + + let mut result = Vec::with_capacity(count); + for i in 0..count { + let string_ptr = (*manglings).Strings.add(i); + result.push(cxstring_to_string_leaky(*string_ptr)); + } + clang_disposeStringSet(manglings); + Ok(result) + } + } + + /// Returns whether the cursor refers to a built-in definition. + pub(crate) fn is_builtin(&self) -> bool { + let (file, _, _, _) = self.location().location(); + file.name().is_none() + } + + /// Get the `Cursor` for this cursor's referent's lexical parent. + /// + /// The lexical parent is the parent of the definition. The semantic parent + /// is the parent of the declaration. Generally, the lexical parent doesn't + /// have any effect on semantics, while the semantic parent does. + /// + /// In the following snippet, the `Foo` class would be the semantic parent + /// of the out-of-line `method` definition, while the lexical parent is the + /// translation unit. + /// + /// ```c++ + /// class Foo { + /// void method(); + /// }; + /// + /// void Foo::method() { /* ... */ } + /// ``` + pub(crate) fn lexical_parent(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getCursorLexicalParent(self.x), + } + } + } + + /// Get the referent's semantic parent, if one is available. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. + pub(crate) fn fallible_semantic_parent(&self) -> Option { + let sp = unsafe { + Cursor { + x: clang_getCursorSemanticParent(self.x), + } + }; + if sp == *self || !sp.is_valid() { + return None; + } + Some(sp) + } + + /// Get the referent's semantic parent. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. + pub(crate) fn semantic_parent(&self) -> Cursor { + self.fallible_semantic_parent().unwrap() + } + + /// Return the number of template arguments used by this cursor's referent, + /// if the referent is either a template instantiation. Returns `None` + /// otherwise. + /// + /// NOTE: This may not return `Some` for partial template specializations, + /// see #193 and #194. + pub(crate) fn num_template_args(&self) -> Option { + // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while + // `clang_Cursor_getNumTemplateArguments` is totally unreliable. + // Therefore, try former first, and only fallback to the latter if we + // have to. + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = + unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical == *self { + None + } else { + canonical.num_template_args() + } + }) + } + + /// Get a cursor pointing to this referent's containing translation unit. + /// + /// Note that we shouldn't create a `TranslationUnit` struct here, because + /// bindgen assumes there will only be one of them alive at a time, and + /// disposes it on drop. That can change if this would be required, but I + /// think we can survive fine without it. + pub(crate) fn translation_unit(&self) -> Cursor { + assert!(self.is_valid()); + unsafe { + let tu = clang_Cursor_getTranslationUnit(self.x); + let cursor = Cursor { + x: clang_getTranslationUnitCursor(tu), + }; + assert!(cursor.is_valid()); + cursor + } + } + + /// Is the referent a top level construct? + pub(crate) fn is_toplevel(&self) -> bool { + let mut semantic_parent = self.fallible_semantic_parent(); + + while semantic_parent.is_some() && + (semantic_parent.unwrap().kind() == CXCursor_Namespace || + semantic_parent.unwrap().kind() == + CXCursor_NamespaceAlias || + semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) + { + semantic_parent = + semantic_parent.unwrap().fallible_semantic_parent(); + } + + let tu = self.translation_unit(); + // Yes, this can happen with, e.g., macro definitions. + semantic_parent == tu.fallible_semantic_parent() + } + + /// There are a few kinds of types that we need to treat specially, mainly + /// not tracking the type declaration but the location of the cursor, given + /// clang doesn't expose a proper declaration for these types. + pub(crate) fn is_template_like(&self) -> bool { + matches!( + self.kind(), + CXCursor_ClassTemplate | + CXCursor_ClassTemplatePartialSpecialization | + CXCursor_TypeAliasTemplateDecl + ) + } + + /// Is this Cursor pointing to a function-like macro definition? + pub(crate) fn is_macro_function_like(&self) -> bool { + unsafe { clang_Cursor_isMacroFunctionLike(self.x) != 0 } + } + + /// Get the kind of referent this cursor is pointing to. + pub(crate) fn kind(&self) -> CXCursorKind { + self.x.kind + } + + /// Returns true if the cursor is a definition + pub(crate) fn is_definition(&self) -> bool { + unsafe { clang_isCursorDefinition(self.x) != 0 } + } + + /// Is the referent a template specialization? + pub(crate) fn is_template_specialization(&self) -> bool { + self.specialized().is_some() + } + + /// Is the referent a fully specialized template specialization without any + /// remaining free template arguments? + pub(crate) fn is_fully_specialized_template(&self) -> bool { + self.is_template_specialization() && + self.kind() != CXCursor_ClassTemplatePartialSpecialization && + self.num_template_args().unwrap_or(0) > 0 + } + + /// Is the referent a template specialization that still has remaining free + /// template arguments? + pub(crate) fn is_in_non_fully_specialized_template(&self) -> bool { + if self.is_toplevel() { + return false; + } + + let parent = self.semantic_parent(); + if parent.is_fully_specialized_template() { + return false; + } + + if !parent.is_template_like() { + return parent.is_in_non_fully_specialized_template(); + } + + true + } + + /// Is the referent any kind of template parameter? + pub(crate) fn is_template_parameter(&self) -> bool { + matches!( + self.kind(), + CXCursor_TemplateTemplateParameter | + CXCursor_TemplateTypeParameter | + CXCursor_NonTypeTemplateParameter + ) + } + + /// Does the referent's type or value depend on a template parameter? + pub(crate) fn is_dependent_on_template_parameter(&self) -> bool { + fn visitor( + found_template_parameter: &mut bool, + cur: Cursor, + ) -> CXChildVisitResult { + // If we found a template parameter, it is dependent. + if cur.is_template_parameter() { + *found_template_parameter = true; + return CXChildVisit_Break; + } + + // Get the referent and traverse it as well. + if let Some(referenced) = cur.referenced() { + if referenced.is_template_parameter() { + *found_template_parameter = true; + return CXChildVisit_Break; + } + + referenced + .visit(|next| visitor(found_template_parameter, next)); + if *found_template_parameter { + return CXChildVisit_Break; + } + } + + // Continue traversing the AST at the original cursor. + CXChildVisit_Recurse + } + + if self.is_template_parameter() { + return true; + } + + let mut found_template_parameter = false; + self.visit(|next| visitor(&mut found_template_parameter, next)); + + found_template_parameter + } + + /// Is this cursor pointing a valid referent? + pub(crate) fn is_valid(&self) -> bool { + unsafe { clang_isInvalid(self.kind()) == 0 } + } + + /// Get the source location for the referent. + pub(crate) fn location(&self) -> SourceLocation { + unsafe { + SourceLocation { + x: clang_getCursorLocation(self.x), + } + } + } + + /// Get the source location range for the referent. + pub(crate) fn extent(&self) -> CXSourceRange { + unsafe { clang_getCursorExtent(self.x) } + } + + /// Get the raw declaration comment for this referent, if one exists. + pub(crate) fn raw_comment(&self) -> Option { + let s = unsafe { + cxstring_into_string(clang_Cursor_getRawCommentText(self.x)) + }; + if s.is_empty() { + None + } else { + Some(s) + } + } + + /// Get the referent's parsed comment. + pub(crate) fn comment(&self) -> Comment { + unsafe { + Comment { + x: clang_Cursor_getParsedComment(self.x), + } + } + } + + /// Get the referent's type. + pub(crate) fn cur_type(&self) -> Type { + unsafe { + Type { + x: clang_getCursorType(self.x), + } + } + } + + /// Given that this cursor's referent is a reference to another type, or is + /// a declaration, get the cursor pointing to the referenced type or type of + /// the declared thing. + pub(crate) fn definition(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getCursorDefinition(self.x), + }; + + if ret.is_valid() && ret.kind() != CXCursor_NoDeclFound { + Some(ret) + } else { + None + } + } + } + + /// Given that this cursor's referent is reference type, get the cursor + /// pointing to the referenced type. + pub(crate) fn referenced(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getCursorReferenced(self.x), + }; + + if ret.is_valid() { + Some(ret) + } else { + None + } + } + } + + /// Get the canonical cursor for this referent. + /// + /// Many types can be declared multiple times before finally being properly + /// defined. This method allows us to get the canonical cursor for the + /// referent type. + pub(crate) fn canonical(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getCanonicalCursor(self.x), + } + } + } + + /// Given that this cursor points to either a template specialization or a + /// template instantiation, get a cursor pointing to the template definition + /// that is being specialized. + pub(crate) fn specialized(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getSpecializedCursorTemplate(self.x), + }; + if ret.is_valid() { + Some(ret) + } else { + None + } + } + } + + /// Assuming that this cursor's referent is a template declaration, get the + /// kind of cursor that would be generated for its specializations. + pub(crate) fn template_kind(&self) -> CXCursorKind { + unsafe { clang_getTemplateCursorKind(self.x) } + } + + /// Traverse this cursor's referent and its children. + /// + /// Call the given function on each AST node traversed. + pub(crate) fn visit(&self, mut visitor: Visitor) + where + Visitor: FnMut(Cursor) -> CXChildVisitResult, + { + let data = ptr::addr_of_mut!(visitor); + unsafe { + clang_visitChildren(self.x, visit_children::, data.cast()); + } + } + + /// Traverse all of this cursor's children, sorted by where they appear in source code. + /// + /// Call the given function on each AST node traversed. + pub(crate) fn visit_sorted( + &self, + ctx: &mut BindgenContext, + mut visitor: Visitor, + ) where + Visitor: FnMut(&mut BindgenContext, Cursor), + { + // FIXME(#2556): The current source order stuff doesn't account well for different levels + // of includes, or includes that show up at the same byte offset because they are passed in + // via CLI. + const SOURCE_ORDER_ENABLED: bool = false; + if !SOURCE_ORDER_ENABLED { + return self.visit(|c| { + visitor(ctx, c); + CXChildVisit_Continue + }); + } + + let mut children = self.collect_children(); + for child in &children { + if child.kind() == CXCursor_InclusionDirective { + if let Some(included_file) = child.get_included_file_name() { + let location = child.location(); + let (source_file, _, _, offset) = location.location(); + + if let Some(source_file) = source_file.name() { + ctx.add_include(source_file, included_file, offset); + } + } + } + } + children + .sort_by(|child1, child2| child1.cmp_by_source_order(child2, ctx)); + for child in children { + visitor(ctx, child); + } + } + + /// Compare source order of two cursors, considering `#include` directives. + /// + /// Built-in items provided by the compiler (which don't have a source file), + /// are sorted first. Remaining files are sorted by their position in the source file. + /// If the items' source files differ, they are sorted by the position of the first + /// `#include` for their source file. If no source files are included, `None` is returned. + fn cmp_by_source_order( + &self, + other: &Self, + ctx: &BindgenContext, + ) -> cmp::Ordering { + let (file, _, _, offset) = self.location().location(); + let (other_file, _, _, other_offset) = other.location().location(); + + let (file, other_file) = match (file.name(), other_file.name()) { + (Some(file), Some(other_file)) => (file, other_file), + // Built-in definitions should come first. + (Some(_), None) => return cmp::Ordering::Greater, + (None, Some(_)) => return cmp::Ordering::Less, + (None, None) => return cmp::Ordering::Equal, + }; + + if file == other_file { + // Both items are in the same source file, compare by byte offset. + return offset.cmp(&other_offset); + } + + let include_location = ctx.included_file_location(&file); + let other_include_location = ctx.included_file_location(&other_file); + match (include_location, other_include_location) { + (Some((file2, offset2)), _) if file2 == other_file => { + offset2.cmp(&other_offset) + } + (Some(_), None) => cmp::Ordering::Greater, + (_, Some((other_file2, other_offset2))) if file == other_file2 => { + offset.cmp(&other_offset2) + } + (None, Some(_)) => cmp::Ordering::Less, + (Some((file2, offset2)), Some((other_file2, other_offset2))) => { + if file2 == other_file2 { + offset2.cmp(&other_offset2) + } else { + cmp::Ordering::Equal + } + } + (None, None) => cmp::Ordering::Equal, + } + } + + /// Collect all of this cursor's children into a vec and return them. + pub(crate) fn collect_children(&self) -> Vec { + let mut children = vec![]; + self.visit(|c| { + children.push(c); + CXChildVisit_Continue + }); + children + } + + /// Does this cursor have any children? + pub(crate) fn has_children(&self) -> bool { + let mut has_children = false; + self.visit(|_| { + has_children = true; + CXChildVisit_Break + }); + has_children + } + + /// Does this cursor have at least `n` children? + pub(crate) fn has_at_least_num_children(&self, n: usize) -> bool { + assert!(n > 0); + let mut num_left = n; + self.visit(|_| { + num_left -= 1; + if num_left == 0 { + CXChildVisit_Break + } else { + CXChildVisit_Continue + } + }); + num_left == 0 + } + + /// Returns whether the given location contains a cursor with the given + /// kind in the first level of nesting underneath (doesn't look + /// recursively). + pub(crate) fn contains_cursor(&self, kind: CXCursorKind) -> bool { + let mut found = false; + + self.visit(|c| { + if c.kind() == kind { + found = true; + CXChildVisit_Break + } else { + CXChildVisit_Continue + } + }); + + found + } + + /// Is the referent an inlined function? + pub(crate) fn is_inlined_function(&self) -> bool { + unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 } + } + + /// Is the referent a defaulted function? + pub(crate) fn is_defaulted_function(&self) -> bool { + unsafe { clang_CXXMethod_isDefaulted(self.x) != 0 } + } + + /// Is the referent a deleted function? + pub(crate) fn is_deleted_function(&self) -> bool { + // Unfortunately, libclang doesn't yet have an API for checking if a + // member function is deleted, but the following should be a good + // enough approximation. + // Deleted functions are implicitly inline according to paragraph 4 of + // [dcl.fct.def.delete] in the C++ standard. Normal inline functions + // have a definition in the same translation unit, so if this is an + // inline function without a definition, and it's not a defaulted + // function, we can reasonably safely conclude that it's a deleted + // function. + self.is_inlined_function() && + self.definition().is_none() && + !self.is_defaulted_function() + } + + /// Is the referent a bit field declaration? + pub(crate) fn is_bit_field(&self) -> bool { + unsafe { clang_Cursor_isBitField(self.x) != 0 } + } + + /// Get a cursor to the bit field's width expression, or `None` if it's not + /// a bit field. + pub(crate) fn bit_width_expr(&self) -> Option { + if !self.is_bit_field() { + return None; + } + + let mut result = None; + self.visit(|cur| { + // The first child may or may not be a TypeRef, depending on whether + // the field's type is builtin. Skip it. + if cur.kind() == CXCursor_TypeRef { + return CXChildVisit_Continue; + } + + // The next expression or literal is the bit width. + result = Some(cur); + + CXChildVisit_Break + }); + + result + } + + /// Get the width of this cursor's referent bit field, or `None` if the + /// referent is not a bit field or if the width could not be evaluated. + pub(crate) fn bit_width(&self) -> Option { + // It is not safe to check the bit width without ensuring it doesn't + // depend on a template parameter. See + // https://github.com/rust-lang/rust-bindgen/issues/2239 + if self.bit_width_expr()?.is_dependent_on_template_parameter() { + return None; + } + + unsafe { + let w = clang_getFieldDeclBitWidth(self.x); + if w == -1 { + None + } else { + Some(w as u32) + } + } + } + + /// Get the integer representation type used to hold this cursor's referent + /// enum type. + pub(crate) fn enum_type(&self) -> Option { + unsafe { + let t = Type { + x: clang_getEnumDeclIntegerType(self.x), + }; + if t.is_valid() { + Some(t) + } else { + None + } + } + } + + /// Get the boolean constant value for this cursor's enum variant referent. + /// + /// Returns None if the cursor's referent is not an enum variant. + pub(crate) fn enum_val_boolean(&self) -> Option { + unsafe { + if self.kind() == CXCursor_EnumConstantDecl { + Some(clang_getEnumConstantDeclValue(self.x) != 0) + } else { + None + } + } + } + + /// Get the signed constant value for this cursor's enum variant referent. + /// + /// Returns None if the cursor's referent is not an enum variant. + pub(crate) fn enum_val_signed(&self) -> Option { + unsafe { + if self.kind() == CXCursor_EnumConstantDecl { + #[allow(clippy::unnecessary_cast)] + Some(clang_getEnumConstantDeclValue(self.x) as i64) + } else { + None + } + } + } + + /// Get the unsigned constant value for this cursor's enum variant referent. + /// + /// Returns None if the cursor's referent is not an enum variant. + pub(crate) fn enum_val_unsigned(&self) -> Option { + unsafe { + if self.kind() == CXCursor_EnumConstantDecl { + #[allow(clippy::unnecessary_cast)] + Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64) + } else { + None + } + } + } + + /// Does this cursor have the given attributes? + pub(crate) fn has_attrs( + &self, + attrs: &[Attribute; N], + ) -> [bool; N] { + let mut found_attrs = [false; N]; + let mut found_count = 0; + + self.visit(|cur| { + let kind = cur.kind(); + for (idx, attr) in attrs.iter().enumerate() { + let found_attr = &mut found_attrs[idx]; + if !*found_attr { + // `attr.name` and` attr.token_kind` are checked against unexposed attributes only. + if attr.kind == Some(kind) || + (kind == CXCursor_UnexposedAttr && + cur.tokens().iter().any(|t| { + t.kind == attr.token_kind && + t.spelling() == attr.name + })) + { + *found_attr = true; + found_count += 1; + + if found_count == N { + return CXChildVisit_Break; + } + } + } + } + + CXChildVisit_Continue + }); + + found_attrs + } + + /// Given that this cursor's referent is a `typedef`, get the `Type` that is + /// being aliased. + pub(crate) fn typedef_type(&self) -> Option { + let inner = Type { + x: unsafe { clang_getTypedefDeclUnderlyingType(self.x) }, + }; + + if inner.is_valid() { + Some(inner) + } else { + None + } + } + + /// Get the linkage kind for this cursor's referent. + /// + /// This only applies to functions and variables. + pub(crate) fn linkage(&self) -> CXLinkageKind { + unsafe { clang_getCursorLinkage(self.x) } + } + + /// Get the visibility of this cursor's referent. + pub(crate) fn visibility(&self) -> CXVisibilityKind { + unsafe { clang_getCursorVisibility(self.x) } + } + + /// Given that this cursor's referent is a function, return cursors to its + /// parameters. + /// + /// Returns None if the cursor's referent is not a function/method call or + /// declaration. + pub(crate) fn args(&self) -> Option> { + // match self.kind() { + // CXCursor_FunctionDecl | + // CXCursor_CXXMethod => { + self.num_args().ok().map(|num| { + (0..num) + .map(|i| Cursor { + x: unsafe { clang_Cursor_getArgument(self.x, i as c_uint) }, + }) + .collect() + }) + } + + /// Given that this cursor's referent is a function/method call or + /// declaration, return the number of arguments it takes. + /// + /// Returns Err if the cursor's referent is not a function/method call or + /// declaration. + pub(crate) fn num_args(&self) -> Result { + unsafe { + let w = clang_Cursor_getNumArguments(self.x); + if w == -1 { + Err(()) + } else { + Ok(w as u32) + } + } + } + + /// Get the access specifier for this cursor's referent. + pub(crate) fn access_specifier(&self) -> CX_CXXAccessSpecifier { + unsafe { clang_getCXXAccessSpecifier(self.x) } + } + + /// Is the cursor's referent publicly accessible in C++? + /// + /// Returns true if `self.access_specifier()` is `CX_CXXPublic` or + /// `CX_CXXInvalidAccessSpecifier`. + pub(crate) fn public_accessible(&self) -> bool { + let access = self.access_specifier(); + access == CX_CXXPublic || access == CX_CXXInvalidAccessSpecifier + } + + /// Is this cursor's referent a field declaration that is marked as + /// `mutable`? + pub(crate) fn is_mutable_field(&self) -> bool { + unsafe { clang_CXXField_isMutable(self.x) != 0 } + } + + /// Get the offset of the field represented by the Cursor. + pub(crate) fn offset_of_field(&self) -> Result { + let offset = unsafe { clang_Cursor_getOffsetOfField(self.x) }; + + if offset < 0 { + Err(LayoutError::from(offset as i32)) + } else { + Ok(offset as usize) + } + } + + /// Is this cursor's referent a member function that is declared `static`? + pub(crate) fn method_is_static(&self) -> bool { + unsafe { clang_CXXMethod_isStatic(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is declared `const`? + pub(crate) fn method_is_const(&self) -> bool { + unsafe { clang_CXXMethod_isConst(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is virtual? + pub(crate) fn method_is_virtual(&self) -> bool { + unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is pure virtual? + pub(crate) fn method_is_pure_virtual(&self) -> bool { + unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 } + } + + /// Is this cursor's referent a struct or class with virtual members? + pub(crate) fn is_virtual_base(&self) -> bool { + unsafe { clang_isVirtualBase(self.x) != 0 } + } + + /// Try to evaluate this cursor. + pub(crate) fn evaluate(&self) -> Option { + EvalResult::new(*self) + } + + /// Return the result type for this cursor + pub(crate) fn ret_type(&self) -> Option { + let rt = Type { + x: unsafe { clang_getCursorResultType(self.x) }, + }; + if rt.is_valid() { + Some(rt) + } else { + None + } + } + + /// Gets the tokens that correspond to that cursor. + pub(crate) fn tokens(&self) -> RawTokens<'_> { + RawTokens::new(self) + } + + /// Gets the tokens that correspond to that cursor as `cexpr` tokens. + pub(crate) fn cexpr_tokens(self) -> Vec { + self.tokens() + .iter() + .filter_map(|token| token.as_cexpr_token()) + .collect() + } + + /// Obtain the real path name of a cursor of `InclusionDirective` kind. + /// + /// Returns None if the cursor does not include a file, otherwise the file's full name + pub(crate) fn get_included_file_name(&self) -> Option { + let file = unsafe { clang_getIncludedFile(self.x) }; + if file.is_null() { + None + } else { + Some(unsafe { cxstring_into_string(clang_getFileName(file)) }) + } + } + + /// Is this cursor's referent a namespace that is inline? + pub(crate) fn is_inline_namespace(&self) -> bool { + unsafe { clang_Cursor_isInlineNamespace(self.x) != 0 } + } +} + +/// A struct that owns the tokenizer result from a given cursor. +pub(crate) struct RawTokens<'a> { + cursor: &'a Cursor, + tu: CXTranslationUnit, + tokens: *mut CXToken, + token_count: c_uint, +} + +impl<'a> RawTokens<'a> { + fn new(cursor: &'a Cursor) -> Self { + let mut tokens = ptr::null_mut(); + let mut token_count = 0; + let range = cursor.extent(); + let tu = unsafe { clang_Cursor_getTranslationUnit(cursor.x) }; + unsafe { clang_tokenize(tu, range, &mut tokens, &mut token_count) }; + Self { + cursor, + tu, + tokens, + token_count, + } + } + + fn as_slice(&self) -> &[CXToken] { + if self.tokens.is_null() { + return &[]; + } + unsafe { slice::from_raw_parts(self.tokens, self.token_count as usize) } + } + + /// Get an iterator over these tokens. + pub(crate) fn iter(&self) -> ClangTokenIterator<'_> { + ClangTokenIterator { + tu: self.tu, + raw: self.as_slice().iter(), + } + } +} + +impl Drop for RawTokens<'_> { + fn drop(&mut self) { + if !self.tokens.is_null() { + unsafe { + clang_disposeTokens( + self.tu, + self.tokens, + self.token_count as c_uint, + ); + } + } + } +} + +/// A raw clang token, that exposes only kind, spelling, and extent. This is a +/// slightly more convenient version of `CXToken` which owns the spelling +/// string and extent. +#[derive(Debug)] +pub(crate) struct ClangToken { + spelling: CXString, + /// The extent of the token. This is the same as the relevant member from + /// `CXToken`. + pub(crate) extent: CXSourceRange, + /// The kind of the token. This is the same as the relevant member from + /// `CXToken`. + pub(crate) kind: CXTokenKind, +} + +impl ClangToken { + /// Get the token spelling, without being converted to utf-8. + pub(crate) fn spelling(&self) -> &[u8] { + let c_str = unsafe { CStr::from_ptr(clang_getCString(self.spelling)) }; + c_str.to_bytes() + } + + /// Converts a `ClangToken` to a `cexpr` token if possible. + pub(crate) fn as_cexpr_token(&self) -> Option { + use cexpr::token; + + let kind = match self.kind { + CXToken_Punctuation => token::Kind::Punctuation, + CXToken_Literal => token::Kind::Literal, + CXToken_Identifier => token::Kind::Identifier, + CXToken_Keyword => token::Kind::Keyword, + // NB: cexpr is not too happy about comments inside + // expressions, so we strip them down here. + CXToken_Comment => return None, + _ => { + warn!("Found unexpected token kind: {self:?}"); + return None; + } + }; + + Some(token::Token { + kind, + raw: self.spelling().to_vec().into_boxed_slice(), + }) + } +} + +impl Drop for ClangToken { + fn drop(&mut self) { + unsafe { clang_disposeString(self.spelling) } + } +} + +/// An iterator over a set of Tokens. +pub(crate) struct ClangTokenIterator<'a> { + tu: CXTranslationUnit, + raw: slice::Iter<'a, CXToken>, +} + +impl Iterator for ClangTokenIterator<'_> { + type Item = ClangToken; + + fn next(&mut self) -> Option { + let raw = self.raw.next()?; + unsafe { + let kind = clang_getTokenKind(*raw); + let spelling = clang_getTokenSpelling(self.tu, *raw); + let extent = clang_getTokenExtent(self.tu, *raw); + Some(ClangToken { + spelling, + extent, + kind, + }) + } + } +} + +/// Checks whether the name looks like an identifier, i.e. is alphanumeric +/// (including '_') and does not start with a digit. +pub(crate) fn is_valid_identifier(name: &str) -> bool { + let mut chars = name.chars(); + let first_valid = + chars.next().is_some_and(|c| c.is_alphabetic() || c == '_'); + + first_valid && chars.all(|c| c.is_alphanumeric() || c == '_') +} + +extern "C" fn visit_children( + cur: CXCursor, + _parent: CXCursor, + data: CXClientData, +) -> CXChildVisitResult +where + Visitor: FnMut(Cursor) -> CXChildVisitResult, +{ + let func: &mut Visitor = unsafe { &mut *data.cast::() }; + let child = Cursor { x: cur }; + + (*func)(child) +} + +impl PartialEq for Cursor { + fn eq(&self, other: &Cursor) -> bool { + unsafe { clang_equalCursors(self.x, other.x) == 1 } + } +} + +impl Eq for Cursor {} + +impl Hash for Cursor { + fn hash(&self, state: &mut H) { + unsafe { clang_hashCursor(self.x) }.hash(state); + } +} + +/// The type of a node in clang's AST. +#[derive(Clone, Copy)] +pub(crate) struct Type { + x: CXType, +} + +impl PartialEq for Type { + fn eq(&self, other: &Self) -> bool { + unsafe { clang_equalTypes(self.x, other.x) != 0 } + } +} + +impl Eq for Type {} + +impl fmt::Debug for Type { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!( + fmt, + "Type({}, kind: {}, cconv: {}, decl: {:?}, canon: {:?})", + self.spelling(), + type_to_str(self.kind()), + self.call_conv(), + self.declaration(), + self.declaration().canonical() + ) + } +} + +/// An error about the layout of a struct, class, or type. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub(crate) enum LayoutError { + /// Asked for the layout of an invalid type. + Invalid, + /// Asked for the layout of an incomplete type. + Incomplete, + /// Asked for the layout of a dependent type. + Dependent, + /// Asked for the layout of a type that does not have constant size. + NotConstantSize, + /// Asked for the layout of a field in a type that does not have such a + /// field. + InvalidFieldName, + /// An unknown layout error. + Unknown, +} + +impl ::std::convert::From for LayoutError { + fn from(val: i32) -> Self { + use self::LayoutError::*; + + match val { + CXTypeLayoutError_Invalid => Invalid, + CXTypeLayoutError_Incomplete => Incomplete, + CXTypeLayoutError_Dependent => Dependent, + CXTypeLayoutError_NotConstantSize => NotConstantSize, + CXTypeLayoutError_InvalidFieldName => InvalidFieldName, + _ => Unknown, + } + } +} + +impl Type { + /// Get this type's kind. + pub(crate) fn kind(&self) -> CXTypeKind { + self.x.kind + } + + /// Get a cursor pointing to this type's declaration. + pub(crate) fn declaration(&self) -> Cursor { + let decl = Cursor { + x: unsafe { clang_getTypeDeclaration(self.x) }, + }; + // Prior to clang 22, the declaration pointed to the definition. + decl.definition().unwrap_or(decl) + } + + /// Get the canonical declaration of this type, if it is available. + pub(crate) fn canonical_declaration( + &self, + location: Option<&Cursor>, + ) -> Option { + let mut declaration = self.declaration(); + if !declaration.is_valid() { + if let Some(location) = location { + let mut location = *location; + if let Some(referenced) = location.referenced() { + location = referenced; + } + if location.is_template_like() { + declaration = location; + } + } + } + + let canonical = declaration.canonical(); + if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound { + Some(CanonicalTypeDeclaration(*self, canonical)) + } else { + None + } + } + + /// Get a raw display name for this type. + pub(crate) fn spelling(&self) -> String { + let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) }; + // Clang 5.0 introduced changes in the spelling API so it returned the + // full qualified name. Let's undo that here. + if s.split("::").all(is_valid_identifier) { + if let Some(s) = s.split("::").last() { + return s.to_owned(); + } + } + + s + } + + /// Is this type const qualified? + pub(crate) fn is_const(&self) -> bool { + unsafe { clang_isConstQualifiedType(self.x) != 0 } + } + + #[inline] + fn is_non_deductible_auto_type(&self) -> bool { + debug_assert_eq!(self.kind(), CXType_Auto); + self.canonical_type() == *self + } + + #[inline] + fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong { + match self.kind() { + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975 + CXType_RValueReference | CXType_LValueReference => { + ctx.target_pointer_size() as c_longlong + } + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + CXType_Auto if self.is_non_deductible_auto_type() => -6, + _ => unsafe { clang_Type_getSizeOf(self.x) }, + } + } + + #[inline] + fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong { + match self.kind() { + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975 + CXType_RValueReference | CXType_LValueReference => { + ctx.target_pointer_size() as c_longlong + } + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + CXType_Auto if self.is_non_deductible_auto_type() => -6, + _ => unsafe { clang_Type_getAlignOf(self.x) }, + } + } + + /// What is the size of this type? Paper over invalid types by returning `0` + /// for them. + pub(crate) fn size(&self, ctx: &BindgenContext) -> usize { + let val = self.clang_size_of(ctx); + if val < 0 { + 0 + } else { + val as usize + } + } + + /// What is the size of this type? + pub(crate) fn fallible_size( + &self, + ctx: &BindgenContext, + ) -> Result { + let val = self.clang_size_of(ctx); + if val < 0 { + Err(LayoutError::from(val as i32)) + } else { + Ok(val as usize) + } + } + + /// What is the alignment of this type? Paper over invalid types by + /// returning `0`. + pub(crate) fn align(&self, ctx: &BindgenContext) -> usize { + let val = self.clang_align_of(ctx); + if val < 0 { + 0 + } else { + val as usize + } + } + + /// What is the alignment of this type? + pub(crate) fn fallible_align( + &self, + ctx: &BindgenContext, + ) -> Result { + let val = self.clang_align_of(ctx); + if val < 0 { + Err(LayoutError::from(val as i32)) + } else { + Ok(val as usize) + } + } + + /// Get the layout for this type, or an error describing why it does not + /// have a valid layout. + pub(crate) fn fallible_layout( + &self, + ctx: &BindgenContext, + ) -> Result { + use crate::ir::layout::Layout; + let size = self.fallible_size(ctx)?; + let align = self.fallible_align(ctx)?; + Ok(Layout::new(size, align)) + } + + /// Get the number of template arguments this type has, or `None` if it is + /// not some kind of template. + pub(crate) fn num_template_args(&self) -> Option { + let n = unsafe { clang_Type_getNumTemplateArguments(self.x) }; + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + } + + /// If this type is a class template specialization, return its + /// template arguments. Otherwise, return None. + pub(crate) fn template_args(&self) -> Option { + self.num_template_args().map(|n| TypeTemplateArgIterator { + x: self.x, + length: n, + index: 0, + }) + } + + /// Given that this type is a function prototype, return the types of its parameters. + /// + /// Returns None if the type is not a function prototype. + pub(crate) fn args(&self) -> Option> { + self.num_args().ok().map(|num| { + (0..num) + .map(|i| Type { + x: unsafe { clang_getArgType(self.x, i as c_uint) }, + }) + .collect() + }) + } + + /// Given that this type is a function prototype, return the number of arguments it takes. + /// + /// Returns Err if the type is not a function prototype. + pub(crate) fn num_args(&self) -> Result { + unsafe { + let w = clang_getNumArgTypes(self.x); + if w == -1 { + Err(()) + } else { + Ok(w as u32) + } + } + } + + /// Given that this type is a pointer type, return the type that it points + /// to. + pub(crate) fn pointee_type(&self) -> Option { + match self.kind() { + CXType_Pointer | + CXType_RValueReference | + CXType_LValueReference | + CXType_MemberPointer | + CXType_BlockPointer | + CXType_ObjCObjectPointer => { + let ret = Type { + x: unsafe { clang_getPointeeType(self.x) }, + }; + debug_assert!(ret.is_valid()); + Some(ret) + } + _ => None, + } + } + + /// Given that this type is an array, vector, or complex type, return the + /// type of its elements. + pub(crate) fn elem_type(&self) -> Option { + let current_type = Type { + x: unsafe { clang_getElementType(self.x) }, + }; + if current_type.is_valid() { + Some(current_type) + } else { + None + } + } + + /// Given that this type is an array or vector type, return its number of + /// elements. + pub(crate) fn num_elements(&self) -> Option { + let num_elements_returned = unsafe { clang_getNumElements(self.x) }; + if num_elements_returned == -1 { + None + } else { + Some(num_elements_returned as usize) + } + } + + /// Get the canonical version of this type. This sees through `typedef`s and + /// aliases to get the underlying, canonical type. + pub(crate) fn canonical_type(&self) -> Type { + unsafe { + Type { + x: clang_getCanonicalType(self.x), + } + } + } + + /// Is this type a variadic function type? + pub(crate) fn is_variadic(&self) -> bool { + unsafe { clang_isFunctionTypeVariadic(self.x) != 0 } + } + + /// Given that this type is a function type, get the type of its return + /// value. + pub(crate) fn ret_type(&self) -> Option { + let rt = Type { + x: unsafe { clang_getResultType(self.x) }, + }; + if rt.is_valid() { + Some(rt) + } else { + None + } + } + + /// Given that this type is a function type, get its calling convention. If + /// this is not a function type, `CXCallingConv_Invalid` is returned. + pub(crate) fn call_conv(&self) -> CXCallingConv { + unsafe { clang_getFunctionTypeCallingConv(self.x) } + } + + /// For elaborated types (types which use `class`, `struct`, or `union` to + /// disambiguate types from local bindings), get the underlying type. + pub(crate) fn named(&self) -> Type { + unsafe { + Type { + x: clang_Type_getNamedType(self.x), + } + } + } + + /// For atomic types, get the underlying type. + pub(crate) fn atomic_value_type(&self) -> Type { + unsafe { + Type { + x: clang_Type_getValueType(self.x), + } + } + } + + /// Is this a valid type? + pub(crate) fn is_valid(&self) -> bool { + self.kind() != CXType_Invalid + } + + /// Is this a valid and exposed type? + pub(crate) fn is_valid_and_exposed(&self) -> bool { + self.is_valid() && self.kind() != CXType_Unexposed + } + + /// Is this type a fully instantiated template? + pub(crate) fn is_fully_instantiated_template(&self) -> bool { + // Yep, the spelling of this containing type-parameter is extremely + // nasty... But can happen in . Unfortunately I couldn't + // reduce it enough :( + self.template_args().is_some_and(|args| args.len() > 0) && + !matches!( + self.declaration().kind(), + CXCursor_ClassTemplatePartialSpecialization | + CXCursor_TypeAliasTemplateDecl | + CXCursor_TemplateTemplateParameter + ) + } + + /// Is this type an associated template type? Eg `T::Associated` in + /// this example: + /// + /// ```c++ + /// template + /// class Foo { + /// typename T::Associated member; + /// }; + /// ``` + pub(crate) fn is_associated_type(&self) -> bool { + // This is terrible :( + fn hacky_parse_associated_type>(spelling: S) -> bool { + static ASSOC_TYPE_RE: OnceLock = OnceLock::new(); + ASSOC_TYPE_RE + .get_or_init(|| { + regex::Regex::new(r"typename type\-parameter\-\d+\-\d+::.+") + .unwrap() + }) + .is_match(spelling.as_ref()) + } + + self.kind() == CXType_Unexposed && + (hacky_parse_associated_type(self.spelling()) || + hacky_parse_associated_type( + self.canonical_type().spelling(), + )) + } +} + +/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its +/// cursor is the canonical declaration for its type. If you have a +/// `CanonicalTypeDeclaration` instance, you know for sure that the type and +/// cursor match up in a canonical declaration relationship, and it simply +/// cannot be otherwise. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct CanonicalTypeDeclaration(Type, Cursor); + +impl CanonicalTypeDeclaration { + /// Get the type. + pub(crate) fn ty(&self) -> &Type { + &self.0 + } + + /// Get the type's canonical declaration cursor. + pub(crate) fn cursor(&self) -> &Cursor { + &self.1 + } +} + +/// An iterator for a type's template arguments. +pub(crate) struct TypeTemplateArgIterator { + x: CXType, + length: u32, + index: u32, +} + +impl Iterator for TypeTemplateArgIterator { + type Item = Type; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index as c_uint; + self.index += 1; + Some(Type { + x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) }, + }) + } else { + None + } + } +} + +impl ExactSizeIterator for TypeTemplateArgIterator { + fn len(&self) -> usize { + assert!(self.index <= self.length); + (self.length - self.index) as usize + } +} + +/// A `SourceLocation` is a file, line, column, and byte offset location for +/// some source text. +pub(crate) struct SourceLocation { + x: CXSourceLocation, +} + +impl SourceLocation { + /// Get the (file, line, column, byte offset) tuple for this source + /// location. + pub(crate) fn location(&self) -> (File, usize, usize, usize) { + unsafe { + let mut file = mem::zeroed(); + let mut line = 0; + let mut col = 0; + let mut off = 0; + clang_getFileLocation( + self.x, &mut file, &mut line, &mut col, &mut off, + ); + (File { x: file }, line as usize, col as usize, off as usize) + } + } +} + +impl fmt::Display for SourceLocation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (file, line, col, _) = self.location(); + if let Some(name) = file.name() { + write!(f, "{name}:{line}:{col}") + } else { + "builtin definitions".fmt(f) + } + } +} + +impl fmt::Debug for SourceLocation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self}") + } +} + +/// A comment in the source text. +/// +/// Comments are sort of parsed by Clang, and have a tree structure. +pub(crate) struct Comment { + x: CXComment, +} + +impl Comment { + /// What kind of comment is this? + pub(crate) fn kind(&self) -> CXCommentKind { + unsafe { clang_Comment_getKind(self.x) } + } + + /// Get this comment's children comment + pub(crate) fn get_children(&self) -> CommentChildrenIterator { + CommentChildrenIterator { + parent: self.x, + length: unsafe { clang_Comment_getNumChildren(self.x) }, + index: 0, + } + } + + /// Given that this comment is the start or end of an HTML tag, get its tag + /// name. + pub(crate) fn get_tag_name(&self) -> String { + unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) } + } + + /// Given that this comment is an HTML start tag, get its attributes. + pub(crate) fn get_tag_attrs(&self) -> CommentAttributesIterator { + CommentAttributesIterator { + x: self.x, + length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) }, + index: 0, + } + } +} + +/// An iterator for a comment's children +pub(crate) struct CommentChildrenIterator { + parent: CXComment, + length: c_uint, + index: c_uint, +} + +impl Iterator for CommentChildrenIterator { + type Item = Comment; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index; + self.index += 1; + Some(Comment { + x: unsafe { clang_Comment_getChild(self.parent, idx) }, + }) + } else { + None + } + } +} + +/// An HTML start tag comment attribute +pub(crate) struct CommentAttribute { + /// HTML start tag attribute name + pub(crate) name: String, + /// HTML start tag attribute value + pub(crate) value: String, +} + +/// An iterator for a comment's attributes +pub(crate) struct CommentAttributesIterator { + x: CXComment, + length: c_uint, + index: c_uint, +} + +impl Iterator for CommentAttributesIterator { + type Item = CommentAttribute; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index; + self.index += 1; + Some(CommentAttribute { + name: unsafe { + cxstring_into_string(clang_HTMLStartTag_getAttrName( + self.x, idx, + )) + }, + value: unsafe { + cxstring_into_string(clang_HTMLStartTag_getAttrValue( + self.x, idx, + )) + }, + }) + } else { + None + } + } +} + +/// A source file. +pub(crate) struct File { + x: CXFile, +} + +impl File { + /// Get the name of this source file. + pub(crate) fn name(&self) -> Option { + if self.x.is_null() { + return None; + } + Some(unsafe { cxstring_into_string(clang_getFileName(self.x)) }) + } +} + +fn cxstring_to_string_leaky(s: CXString) -> String { + if s.data.is_null() { + return String::new(); + } + let c_str = unsafe { CStr::from_ptr(clang_getCString(s)) }; + c_str.to_string_lossy().into_owned() +} + +fn cxstring_into_string(s: CXString) -> String { + let ret = cxstring_to_string_leaky(s); + unsafe { clang_disposeString(s) }; + ret +} + +/// An `Index` is an environment for a set of translation units that will +/// typically end up linked together in one final binary. +pub(crate) struct Index { + x: CXIndex, +} + +impl Index { + /// Construct a new `Index`. + /// + /// The `pch` parameter controls whether declarations in pre-compiled + /// headers are included when enumerating a translation unit's "locals". + /// + /// The `diag` parameter controls whether debugging diagnostics are enabled. + pub(crate) fn new(pch: bool, diag: bool) -> Index { + unsafe { + Index { + x: clang_createIndex(c_int::from(pch), c_int::from(diag)), + } + } + } +} + +impl fmt::Debug for Index { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "Index {{ }}") + } +} + +impl Drop for Index { + fn drop(&mut self) { + unsafe { + clang_disposeIndex(self.x); + } + } +} + +/// A translation unit (or "compilation unit"). +pub(crate) struct TranslationUnit { + x: CXTranslationUnit, +} + +impl fmt::Debug for TranslationUnit { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "TranslationUnit {{ }}") + } +} + +impl TranslationUnit { + /// Parse a source file into a translation unit. + pub(crate) fn parse( + ix: &Index, + file: &str, + cmd_args: &[Box], + unsaved: &[UnsavedFile], + opts: CXTranslationUnit_Flags, + ) -> Option { + let fname = CString::new(file).unwrap(); + let _c_args: Vec = cmd_args + .iter() + .map(|s| CString::new(s.as_bytes()).unwrap()) + .collect(); + let c_args: Vec<*const c_char> = + _c_args.iter().map(|s| s.as_ptr()).collect(); + let mut c_unsaved: Vec = + unsaved.iter().map(|f| f.x).collect(); + let tu = unsafe { + clang_parseTranslationUnit( + ix.x, + fname.as_ptr(), + c_args.as_ptr(), + c_args.len() as c_int, + c_unsaved.as_mut_ptr(), + c_unsaved.len() as c_uint, + opts, + ) + }; + if tu.is_null() { + None + } else { + Some(TranslationUnit { x: tu }) + } + } + + /// Get the Clang diagnostic information associated with this translation + /// unit. + pub(crate) fn diags(&self) -> Vec { + unsafe { + let num = clang_getNumDiagnostics(self.x) as usize; + let mut diags = vec![]; + for i in 0..num { + diags.push(Diagnostic { + x: clang_getDiagnostic(self.x, i as c_uint), + }); + } + diags + } + } + + /// Get a cursor pointing to the root of this translation unit's AST. + pub(crate) fn cursor(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getTranslationUnitCursor(self.x), + } + } + } + + /// Save a translation unit to the given file. + pub(crate) fn save(&mut self, file: &str) -> Result<(), CXSaveError> { + let Ok(file) = CString::new(file) else { + return Err(CXSaveError_Unknown); + }; + let ret = unsafe { + clang_saveTranslationUnit( + self.x, + file.as_ptr(), + clang_defaultSaveOptions(self.x), + ) + }; + if ret != 0 { + Err(ret) + } else { + Ok(()) + } + } + + /// Is this the null translation unit? + pub(crate) fn is_null(&self) -> bool { + self.x.is_null() + } +} + +impl Drop for TranslationUnit { + fn drop(&mut self) { + unsafe { + clang_disposeTranslationUnit(self.x); + } + } +} + +/// Translation unit used for macro fallback parsing +pub(crate) struct FallbackTranslationUnit { + file_path: String, + pch_path: String, + idx: Box, + tu: TranslationUnit, +} + +impl fmt::Debug for FallbackTranslationUnit { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "FallbackTranslationUnit {{ }}") + } +} + +impl FallbackTranslationUnit { + /// Create a new fallback translation unit + pub(crate) fn new( + file: String, + pch_path: String, + c_args: &[Box], + ) -> Option { + // Create empty file + OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&file) + .ok()?; + + let f_index = Box::new(Index::new(true, false)); + let f_translation_unit = TranslationUnit::parse( + &f_index, + &file, + c_args, + &[], + CXTranslationUnit_None, + )?; + Some(FallbackTranslationUnit { + file_path: file, + pch_path, + tu: f_translation_unit, + idx: f_index, + }) + } + + /// Get reference to underlying translation unit. + pub(crate) fn translation_unit(&self) -> &TranslationUnit { + &self.tu + } + + /// Reparse a translation unit. + pub(crate) fn reparse( + &mut self, + unsaved_contents: &str, + ) -> Result<(), CXErrorCode> { + let unsaved = &[UnsavedFile::new(&self.file_path, unsaved_contents)]; + let mut c_unsaved: Vec = + unsaved.iter().map(|f| f.x).collect(); + let ret = unsafe { + clang_reparseTranslationUnit( + self.tu.x, + unsaved.len() as c_uint, + c_unsaved.as_mut_ptr(), + clang_defaultReparseOptions(self.tu.x), + ) + }; + if ret != 0 { + Err(ret) + } else { + Ok(()) + } + } +} + +impl Drop for FallbackTranslationUnit { + fn drop(&mut self) { + let _ = std::fs::remove_file(&self.file_path); + let _ = std::fs::remove_file(&self.pch_path); + } +} + +/// A diagnostic message generated while parsing a translation unit. +pub(crate) struct Diagnostic { + x: CXDiagnostic, +} + +impl Diagnostic { + /// Format this diagnostic message as a string, using the given option bit + /// flags. + pub(crate) fn format(&self) -> String { + unsafe { + let opts = clang_defaultDiagnosticDisplayOptions(); + cxstring_into_string(clang_formatDiagnostic(self.x, opts)) + } + } + + /// What is the severity of this diagnostic message? + pub(crate) fn severity(&self) -> CXDiagnosticSeverity { + unsafe { clang_getDiagnosticSeverity(self.x) } + } +} + +impl Drop for Diagnostic { + /// Destroy this diagnostic message. + fn drop(&mut self) { + unsafe { + clang_disposeDiagnostic(self.x); + } + } +} + +/// A file which has not been saved to disk. +pub(crate) struct UnsavedFile { + x: CXUnsavedFile, + /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in + /// `CXUnsavedFile`. + pub(crate) name: CString, + contents: CString, +} + +impl UnsavedFile { + /// Construct a new unsaved file with the given `name` and `contents`. + pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile { + let name = CString::new(name.as_bytes()).unwrap(); + let contents = CString::new(contents.as_bytes()).unwrap(); + let x = CXUnsavedFile { + Filename: name.as_ptr(), + Contents: contents.as_ptr(), + Length: contents.as_bytes().len() as c_ulong, + }; + UnsavedFile { x, name, contents } + } +} + +impl fmt::Debug for UnsavedFile { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!( + fmt, + "UnsavedFile(name: {:?}, contents: {:?})", + self.name, self.contents + ) + } +} + +/// Convert a cursor kind into a static string. +pub(crate) fn kind_to_str(x: CXCursorKind) -> String { + unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) } +} + +/// Convert a type kind to a static string. +pub(crate) fn type_to_str(x: CXTypeKind) -> String { + unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) } +} + +/// Dump the Clang AST to stdout for debugging purposes. +pub(crate) fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult { + fn print_indent>(depth: isize, s: S) { + for _ in 0..depth { + print!(" "); + } + println!("{}", s.as_ref()); + } + + fn print_cursor>(depth: isize, prefix: S, c: &Cursor) { + let prefix = prefix.as_ref(); + print_indent( + depth, + format!(" {prefix}kind = {}", kind_to_str(c.kind())), + ); + print_indent( + depth, + format!(" {prefix}spelling = \"{}\"", c.spelling()), + ); + print_indent(depth, format!(" {prefix}location = {}", c.location())); + print_indent( + depth, + format!(" {prefix}is-definition? {}", c.is_definition()), + ); + print_indent( + depth, + format!(" {prefix}is-declaration? {}", c.is_declaration()), + ); + print_indent( + depth, + format!( + " {prefix}is-inlined-function? {}", + c.is_inlined_function() + ), + ); + + let templ_kind = c.template_kind(); + if templ_kind != CXCursor_NoDeclFound { + print_indent( + depth, + format!(" {prefix}template-kind = {}", kind_to_str(templ_kind)), + ); + } + if let Some(usr) = c.usr() { + print_indent(depth, format!(" {prefix}usr = \"{usr}\"")); + } + if let Ok(num) = c.num_args() { + print_indent(depth, format!(" {prefix}number-of-args = {num}")); + } + if let Some(num) = c.num_template_args() { + print_indent( + depth, + format!(" {prefix}number-of-template-args = {num}"), + ); + } + + if c.is_bit_field() { + let width = match c.bit_width() { + Some(w) => w.to_string(), + None => "".to_string(), + }; + print_indent(depth, format!(" {prefix}bit-width = {width}")); + } + + if let Some(ty) = c.enum_type() { + print_indent( + depth, + format!(" {prefix}enum-type = {}", type_to_str(ty.kind())), + ); + } + if let Some(val) = c.enum_val_signed() { + print_indent(depth, format!(" {prefix}enum-val = {val}")); + } + if let Some(ty) = c.typedef_type() { + print_indent( + depth, + format!(" {prefix}typedef-type = {}", type_to_str(ty.kind())), + ); + } + if let Some(ty) = c.ret_type() { + print_indent( + depth, + format!(" {prefix}ret-type = {}", type_to_str(ty.kind())), + ); + } + + if let Some(refd) = c.referenced() { + if refd != *c { + println!(); + print_cursor( + depth, + String::from(prefix) + "referenced.", + &refd, + ); + } + } + + let canonical = c.canonical(); + if canonical != *c { + println!(); + print_cursor( + depth, + String::from(prefix) + "canonical.", + &canonical, + ); + } + + if let Some(specialized) = c.specialized() { + if specialized != *c { + println!(); + print_cursor( + depth, + String::from(prefix) + "specialized.", + &specialized, + ); + } + } + + if let Some(parent) = c.fallible_semantic_parent() { + println!(); + print_cursor( + depth, + String::from(prefix) + "semantic-parent.", + &parent, + ); + } + } + + fn print_type>(depth: isize, prefix: S, ty: &Type) { + let prefix = prefix.as_ref(); + + let kind = ty.kind(); + print_indent(depth, format!(" {prefix}kind = {}", type_to_str(kind))); + if kind == CXType_Invalid { + return; + } + + print_indent(depth, format!(" {prefix}cconv = {}", ty.call_conv())); + + print_indent( + depth, + format!(" {prefix}spelling = \"{}\"", ty.spelling()), + ); + let num_template_args = + unsafe { clang_Type_getNumTemplateArguments(ty.x) }; + if num_template_args >= 0 { + print_indent( + depth, + format!( + " {prefix}number-of-template-args = {num_template_args}" + ), + ); + } + if let Some(num) = ty.num_elements() { + print_indent(depth, format!(" {prefix}number-of-elements = {num}")); + } + print_indent( + depth, + format!(" {prefix}is-variadic? {}", ty.is_variadic()), + ); + + let canonical = ty.canonical_type(); + if canonical != *ty { + println!(); + print_type(depth, String::from(prefix) + "canonical.", &canonical); + } + + if let Some(pointee) = ty.pointee_type() { + if pointee != *ty { + println!(); + print_type(depth, String::from(prefix) + "pointee.", &pointee); + } + } + + if let Some(elem) = ty.elem_type() { + if elem != *ty { + println!(); + print_type(depth, String::from(prefix) + "elements.", &elem); + } + } + + if let Some(ret) = ty.ret_type() { + if ret != *ty { + println!(); + print_type(depth, String::from(prefix) + "return.", &ret); + } + } + + let named = ty.named(); + if named != *ty && named.is_valid() { + println!(); + print_type(depth, String::from(prefix) + "named.", &named); + } + } + + print_indent(depth, "("); + print_cursor(depth, "", c); + + println!(); + let ty = c.cur_type(); + print_type(depth, "type.", &ty); + + let declaration = ty.declaration(); + if declaration != *c && declaration.kind() != CXCursor_NoDeclFound { + println!(); + print_cursor(depth, "type.declaration.", &declaration); + } + + // Recurse. + let mut found_children = false; + c.visit(|s| { + if !found_children { + println!(); + found_children = true; + } + ast_dump(&s, depth + 1) + }); + + print_indent(depth, ")"); + + CXChildVisit_Continue +} + +/// Try to extract the clang version to a string +pub(crate) fn extract_clang_version() -> String { + unsafe { cxstring_into_string(clang_getClangVersion()) } +} + +/// A wrapper for the result of evaluating an expression. +#[derive(Debug)] +pub(crate) struct EvalResult { + x: CXEvalResult, + ty: Type, +} + +impl EvalResult { + /// Evaluate `cursor` and return the result. + pub(crate) fn new(cursor: Cursor) -> Option { + // Work around https://bugs.llvm.org/show_bug.cgi?id=42532, see: + // * https://github.com/rust-lang/rust-bindgen/issues/283 + // * https://github.com/rust-lang/rust-bindgen/issues/1590 + { + let mut found_cant_eval = false; + cursor.visit(|c| { + if c.kind() == CXCursor_TypeRef && + c.cur_type().canonical_type().kind() == CXType_Unexposed + { + found_cant_eval = true; + return CXChildVisit_Break; + } + + CXChildVisit_Recurse + }); + + if found_cant_eval { + return None; + } + } + Some(EvalResult { + x: unsafe { clang_Cursor_Evaluate(cursor.x) }, + ty: cursor.cur_type().canonical_type(), + }) + } + + fn kind(&self) -> CXEvalResultKind { + unsafe { clang_EvalResult_getKind(self.x) } + } + + /// Try to get back the result as a double. + pub(crate) fn as_double(&self) -> Option { + match self.kind() { + CXEval_Float => { + Some(unsafe { clang_EvalResult_getAsDouble(self.x) }) + } + _ => None, + } + } + + /// Try to get back the result as an integer. + pub(crate) fn as_int(&self) -> Option { + if self.kind() != CXEval_Int { + return None; + } + + if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 { + let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) }; + if value > u64::MAX as c_ulonglong { + return None; + } + + // Do a wrapping cast to i64. This will be losslessly cast back to u64 later. + return Some(value as i64); + } + + let value = unsafe { clang_EvalResult_getAsLongLong(self.x) }; + if value > i64::MAX as c_longlong { + return None; + } + if value < i64::MIN as c_longlong { + return None; + } + #[allow(clippy::unnecessary_cast)] + Some(value as i64) + } + + /// Evaluates the expression as a literal string, that may or may not be + /// valid utf-8. + pub(crate) fn as_literal_string(&self) -> Option> { + if self.kind() != CXEval_StrLiteral { + return None; + } + + let char_ty = self.ty.pointee_type().or_else(|| self.ty.elem_type())?; + match char_ty.kind() { + CXType_Char_S | CXType_SChar | CXType_Char_U | CXType_UChar => { + let ret = unsafe { + CStr::from_ptr(clang_EvalResult_getAsStr(self.x)) + }; + Some(ret.to_bytes().to_vec()) + } + // FIXME: Support generating these. + CXType_Char16 => None, + CXType_Char32 => None, + CXType_WChar => None, + _ => None, + } + } +} + +impl Drop for EvalResult { + fn drop(&mut self) { + unsafe { clang_EvalResult_dispose(self.x) }; + } +} +/// ABI kinds as defined in +/// +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub(crate) enum ABIKind { + /// All the regular targets like Linux, Mac, WASM, etc. implement the Itanium ABI + GenericItanium, + /// The ABI used when compiling for the MSVC target + Microsoft, +} + +/// Target information obtained from libclang. +#[derive(Debug)] +pub(crate) struct TargetInfo { + /// The target triple. + pub(crate) triple: String, + /// The width of the pointer _in bits_. + pub(crate) pointer_width: usize, + /// The ABI of the target + pub(crate) abi: ABIKind, +} + +impl TargetInfo { + /// Tries to obtain target information from libclang. + pub(crate) fn new(tu: &TranslationUnit) -> Self { + let triple; + let pointer_width; + unsafe { + let ti = clang_getTranslationUnitTargetInfo(tu.x); + triple = cxstring_into_string(clang_TargetInfo_getTriple(ti)); + pointer_width = clang_TargetInfo_getPointerWidth(ti); + clang_TargetInfo_dispose(ti); + } + assert!(pointer_width > 0); + assert_eq!(pointer_width % 8, 0); + + let abi = if triple.contains("msvc") { + ABIKind::Microsoft + } else { + ABIKind::GenericItanium + }; + + TargetInfo { + triple, + pointer_width: pointer_width as usize, + abi, + } + } +} diff --git a/bindgen/codegen/bitfield_unit.rs b/bindgen/codegen/bitfield_unit.rs new file mode 100644 index 0000000000..8be311e311 --- /dev/null +++ b/bindgen/codegen/bitfield_unit.rs @@ -0,0 +1,195 @@ +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} + +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} + +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + + let mask = 1 << bit_index; + + byte & mask == mask + } + + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + + Self::extract_bit(byte, index) + } + + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + + Self::extract_bit(byte, index) + } + + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + + let mask = 1 << bit_index; + if val { + byte | mask + } else { + byte & !mask + } + } + + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + + *byte = Self::change_bit(*byte, index, val); + } + + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= + self.storage.as_ref().len() + ); + + let mut val = 0; + + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + + val + } + + #[inline] + pub unsafe fn raw_get( + this: *const Self, + bit_offset: usize, + bit_width: u8, + ) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= + core::mem::size_of::() + ); + + let mut val = 0; + + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + + val + } + + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= + self.storage.as_ref().len() + ); + + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + + #[inline] + pub unsafe fn raw_set( + this: *mut Self, + bit_offset: usize, + bit_width: u8, + val: u64, + ) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= + core::mem::size_of::() + ); + + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { + Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) + }; + } + } +} diff --git a/src/codegen/bitfield_unit_tests.rs b/bindgen/codegen/bitfield_unit_tests.rs similarity index 80% rename from src/codegen/bitfield_unit_tests.rs rename to bindgen/codegen/bitfield_unit_tests.rs index d39878ccd9..ead0ffec0c 100644 --- a/src/codegen/bitfield_unit_tests.rs +++ b/bindgen/codegen/bitfield_unit_tests.rs @@ -22,11 +22,10 @@ //! ``` use super::bitfield_unit::__BindgenBitfieldUnit; -use std::mem; #[test] fn bitfield_unit_get_bit() { - let unit = __BindgenBitfieldUnit::<[u8; 2], u64>::new([0b10011101, 0b00011101]); + let unit = __BindgenBitfieldUnit::<[u8; 2]>::new([0b10011101, 0b00011101]); let mut bits = vec![]; for i in 0..16 { @@ -34,33 +33,22 @@ fn bitfield_unit_get_bit() { } println!(); - println!("bits = {:?}", bits); - assert_eq!(bits, &[ - // 0b10011101 - true, - false, - true, - true, - true, - false, - false, - true , - - // 0b00011101 - true, - false, - true, - true, - true, - false, - false, - false - ]); + println!("bits = {bits:?}"); + assert_eq!( + bits, + &[ + // 0b10011101 + true, false, true, true, true, false, false, true, + // 0b00011101 + true, false, true, true, true, false, false, false + ] + ); } #[test] fn bitfield_unit_set_bit() { - let mut unit = __BindgenBitfieldUnit::<[u8; 2], u64>::new([0b00000000, 0b00000000]); + let mut unit = + __BindgenBitfieldUnit::<[u8; 2]>::new([0b00000000, 0b00000000]); for i in 0..16 { if i % 3 == 0 { @@ -72,7 +60,8 @@ fn bitfield_unit_set_bit() { assert_eq!(unit.get_bit(i), i % 3 == 0); } - let mut unit = __BindgenBitfieldUnit::<[u8; 2], u64>::new([0b11111111, 0b11111111]); + let mut unit = + __BindgenBitfieldUnit::<[u8; 2]>::new([0b11111111, 0b11111111]); for i in 0..16 { if i % 3 == 0 { @@ -85,19 +74,6 @@ fn bitfield_unit_set_bit() { } } -#[test] -fn bitfield_unit_align() { - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u8>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u16>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u32>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u64>>(), mem::align_of::()); - - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u8>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u16>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u32>>(), mem::align_of::()); - assert_eq!(mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u64>>(), mem::align_of::()); -} - macro_rules! bitfield_unit_get { ( $( @@ -108,12 +84,12 @@ macro_rules! bitfield_unit_get { fn bitfield_unit_get() { $({ let expected = $expected; - let unit = __BindgenBitfieldUnit::<_, u64>::new($storage); + let unit = __BindgenBitfieldUnit::<_>::new($storage); let actual = unit.get($start, $len); println!(); - println!("expected = {:064b}", expected); - println!("actual = {:064b}", actual); + println!("expected = {expected:064b}"); + println!("actual = {actual:064b}"); assert_eq!(expected, actual); })* @@ -208,14 +184,14 @@ macro_rules! bitfield_unit_set { #[test] fn bitfield_unit_set() { $( - let mut unit = __BindgenBitfieldUnit::<[u8; 4], u64>::new([0, 0, 0, 0]); + let mut unit = __BindgenBitfieldUnit::<[u8; 4]>::new([0, 0, 0, 0]); unit.set($start, $len, $val); let actual = unit.get(0, 32); println!(); println!("set({}, {}, {:032b}", $start, $len, $val); println!("expected = {:064b}", $expected); - println!("actual = {:064b}", actual); + println!("actual = {actual:064b}"); assert_eq!($expected, actual); )* diff --git a/bindgen/codegen/dyngen.rs b/bindgen/codegen/dyngen.rs new file mode 100644 index 0000000000..76f3805795 --- /dev/null +++ b/bindgen/codegen/dyngen.rs @@ -0,0 +1,258 @@ +use crate::codegen; +use crate::ir::context::BindgenContext; +use crate::ir::function::ClangAbi; +use proc_macro2::{Ident, TokenStream}; + +/// Used to build the output tokens for dynamic bindings. +#[derive(Default)] +pub(crate) struct DynamicItems { + /// Tracks the tokens that will appears inside the library struct -- e.g.: + /// ```ignore + /// struct Lib { + /// __library: ::libloading::Library, + /// pub x: Result, // <- tracks these + /// ... + /// } + /// ``` + struct_members: Vec, + + /// Tracks the tokens that will appear inside the library struct's implementation, e.g.: + /// + /// ```ignore + /// impl Lib { + /// ... + /// pub unsafe fn foo(&self, ...) { // <- tracks these + /// ... + /// } + /// } + /// ``` + struct_implementation: Vec, + + /// Tracks the initialization of the fields inside the `::new` constructor of the library + /// struct, e.g.: + /// ```ignore + /// impl Lib { + /// + /// pub unsafe fn new

(path: P) -> Result + /// where + /// P: AsRef<::std::ffi::OsStr>, + /// { + /// ... + /// let foo = __library.get(...) ...; // <- tracks these + /// ... + /// } + /// + /// ... + /// } + /// ``` + constructor_inits: Vec, + + /// Tracks the information that is passed to the library struct at the end of the `::new` + /// constructor, e.g.: + /// ```ignore + /// impl LibFoo { + /// pub unsafe fn new

(path: P) -> Result + /// where + /// P: AsRef<::std::ffi::OsStr>, + /// { + /// ... + /// Ok(LibFoo { + /// __library: __library, + /// foo, + /// bar, // <- tracks these + /// ... + /// }) + /// } + /// } + /// ``` + init_fields: Vec, +} + +impl DynamicItems { + pub(crate) fn new() -> Self { + Self::default() + } + + pub(crate) fn get_tokens( + &self, + lib_ident: &Ident, + ctx: &BindgenContext, + ) -> TokenStream { + let struct_members = &self.struct_members; + let constructor_inits = &self.constructor_inits; + let init_fields = &self.init_fields; + let struct_implementation = &self.struct_implementation; + + let library_new = if ctx.options().wrap_unsafe_ops { + quote!(unsafe { ::libloading::Library::new(path) }) + } else { + quote!(::libloading::Library::new(path)) + }; + + let from_library = if ctx.options().wrap_unsafe_ops { + quote!(unsafe { Self::from_library(library) }) + } else { + quote!(Self::from_library(library)) + }; + + quote! { + pub struct #lib_ident { + __library: ::libloading::Library, + #(#struct_members)* + } + + impl #lib_ident { + pub unsafe fn new

*/ + /// Baz = 0, + /// }; + /// ``` + /// + /// In that case, bindgen will generate a constant for `Bar` instead of + /// `Baz`. + constify_enum_variant: bool, + /// List of explicit derives for this type. + derives: Vec, + /// List of explicit attributes for this type. + attributes: Vec, +} + +fn parse_accessor(s: &str) -> FieldAccessorKind { + match s { + "false" => FieldAccessorKind::None, + "unsafe" => FieldAccessorKind::Unsafe, + "immutable" => FieldAccessorKind::Immutable, + _ => FieldAccessorKind::Regular, + } +} + +impl Annotations { + /// Construct new annotations for the given cursor and its bindgen comments + /// (if any). + pub(crate) fn new(cursor: &clang::Cursor) -> Option { + let mut anno = Annotations::default(); + let mut matched_one = false; + anno.parse(&cursor.comment(), &mut matched_one); + + if matched_one { + Some(anno) + } else { + None + } + } + + /// Should this type be hidden? + pub(crate) fn hide(&self) -> bool { + self.hide + } + + /// Should this type be opaque? + pub(crate) fn opaque(&self) -> bool { + self.opaque + } + + /// For a given type, indicates the type it should replace. + /// + /// For example, in the following code: + /// + /// ```cpp + /// + /// /**
*/ + /// struct Foo { int x; }; + /// + /// struct Bar { char foo; }; + /// ``` + /// + /// the generated code would look something like: + /// + /// ``` + /// /**
*/ + /// struct Bar { + /// x: ::std::os::raw::c_int, + /// }; + /// ``` + /// + /// That is, code for `Foo` is used to generate `Bar`. + pub(crate) fn use_instead_of(&self) -> Option<&[String]> { + self.use_instead_of.as_deref() + } + + /// The list of derives that have been specified in this annotation. + pub(crate) fn derives(&self) -> &[String] { + &self.derives + } + + /// The list of attributes that have been specified in this annotation. + pub(crate) fn attributes(&self) -> &[String] { + &self.attributes + } + + /// Should we avoid implementing the `Copy` trait? + pub(crate) fn disallow_copy(&self) -> bool { + self.disallow_copy + } + + /// Should we avoid implementing the `Debug` trait? + pub(crate) fn disallow_debug(&self) -> bool { + self.disallow_debug + } + + /// Should we avoid implementing the `Default` trait? + pub(crate) fn disallow_default(&self) -> bool { + self.disallow_default + } + + /// Should this type get a `#[must_use]` annotation? + pub(crate) fn must_use_type(&self) -> bool { + self.must_use_type + } + + /// What kind of accessors should we provide for this type's fields? + pub(crate) fn visibility_kind(&self) -> Option { + self.visibility_kind + } + + /// What kind of accessors should we provide for this type's fields? + pub(crate) fn accessor_kind(&self) -> Option { + self.accessor_kind + } + + fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) { + use clang_sys::CXComment_HTMLStartTag; + if comment.kind() == CXComment_HTMLStartTag && + comment.get_tag_name() == "div" && + comment + .get_tag_attrs() + .next() + .is_some_and(|attr| attr.name == "rustbindgen") + { + *matched = true; + for attr in comment.get_tag_attrs() { + match attr.name.as_str() { + "opaque" => self.opaque = true, + "hide" => self.hide = true, + "nocopy" => self.disallow_copy = true, + "nodebug" => self.disallow_debug = true, + "nodefault" => self.disallow_default = true, + "mustusetype" => self.must_use_type = true, + "replaces" => { + self.use_instead_of = Some( + attr.value.split("::").map(Into::into).collect(), + ); + } + "derive" => self.derives.push(attr.value), + "attribute" => self.attributes.push(attr.value), + "private" => { + self.visibility_kind = if attr.value == "false" { + Some(FieldVisibilityKind::Public) + } else { + Some(FieldVisibilityKind::Private) + }; + } + "accessor" => { + self.accessor_kind = Some(parse_accessor(&attr.value)); + } + "constant" => self.constify_enum_variant = true, + _ => {} + } + } + } + + for child in comment.get_children() { + self.parse(&child, matched); + } + } + + /// Returns whether we've parsed a "constant" attribute. + pub(crate) fn constify_enum_variant(&self) -> bool { + self.constify_enum_variant + } +} diff --git a/bindgen/ir/comment.rs b/bindgen/ir/comment.rs new file mode 100644 index 0000000000..a4ba320186 --- /dev/null +++ b/bindgen/ir/comment.rs @@ -0,0 +1,100 @@ +//! Utilities for manipulating C/C++ comments. + +/// The type of a comment. +#[derive(Debug, PartialEq, Eq)] +enum Kind { + /// A `///` comment, or something of the like. + /// All lines in a comment should start with the same symbol. + SingleLines, + /// A `/**` comment, where each other line can start with `*` and the + /// entire block ends with `*/`. + MultiLine, +} + +/// Preprocesses a C/C++ comment so that it is a valid Rust comment. +pub(crate) fn preprocess(comment: &str) -> String { + match kind(comment) { + Some(Kind::SingleLines) => preprocess_single_lines(comment), + Some(Kind::MultiLine) => preprocess_multi_line(comment), + None => comment.to_owned(), + } +} + +/// Gets the kind of the doc comment, if it is one. +fn kind(comment: &str) -> Option { + if comment.starts_with("/*") { + Some(Kind::MultiLine) + } else if comment.starts_with("//") { + Some(Kind::SingleLines) + } else { + None + } +} + +/// Preprocesses multiple single line comments. +/// +/// Handles lines starting with both `//` and `///`. +fn preprocess_single_lines(comment: &str) -> String { + debug_assert!(comment.starts_with("//"), "comment is not single line"); + + let lines: Vec<_> = comment + .lines() + .map(|l| l.trim().trim_start_matches('/')) + .collect(); + lines.join("\n") +} + +fn preprocess_multi_line(comment: &str) -> String { + let comment = comment + .trim_start_matches('/') + .trim_end_matches('/') + .trim_end_matches('*'); + + // Strip any potential `*` characters preceding each line. + let mut lines: Vec<_> = comment + .lines() + .map(|line| line.trim().trim_start_matches('*').trim_start_matches('!')) + .skip_while(|line| line.trim().is_empty()) // Skip the first empty lines. + .collect(); + + // Remove the trailing line corresponding to the `*/`. + if lines.last().is_some_and(|l| l.trim().is_empty()) { + lines.pop(); + } + + lines.join("\n") +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn picks_up_single_and_multi_line_doc_comments() { + assert_eq!(kind("/// hello"), Some(Kind::SingleLines)); + assert_eq!(kind("/** world */"), Some(Kind::MultiLine)); + } + + #[test] + fn processes_single_lines_correctly() { + assert_eq!(preprocess("///"), ""); + assert_eq!(preprocess("/// hello"), " hello"); + assert_eq!(preprocess("// hello"), " hello"); + assert_eq!(preprocess("// hello"), " hello"); + } + + #[test] + fn processes_multi_lines_correctly() { + assert_eq!(preprocess("/**/"), ""); + + assert_eq!( + preprocess("/** hello \n * world \n * foo \n */"), + " hello\n world\n foo" + ); + + assert_eq!( + preprocess("/**\nhello\n*world\n*foo\n*/"), + "hello\nworld\nfoo" + ); + } +} diff --git a/bindgen/ir/comp.rs b/bindgen/ir/comp.rs new file mode 100644 index 0000000000..c67f9a2597 --- /dev/null +++ b/bindgen/ir/comp.rs @@ -0,0 +1,1873 @@ +//! Compound types (unions and structs) in our intermediate representation. + +use itertools::Itertools; + +use super::analysis::Sizedness; +use super::annotations::Annotations; +use super::context::{BindgenContext, FunctionId, ItemId, TypeId, VarId}; +use super::dot::DotAttributes; +use super::item::{IsOpaque, Item}; +use super::layout::Layout; +use super::template::TemplateParameters; +use super::traversal::{EdgeKind, Trace, Tracer}; +use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; +use crate::clang; +use crate::codegen::struct_layout::align_to; +use crate::ir::derive::CanDeriveCopy; +use crate::parse::ParseError; +use crate::HashMap; +use crate::NonCopyUnionStyle; +use std::cmp; +use std::io; +use std::mem; + +/// The kind of compound type. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum CompKind { + /// A struct. + Struct, + /// A union. + Union, +} + +/// The kind of C++ method. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum MethodKind { + /// A constructor. We represent it as method for convenience, to avoid code + /// duplication. + Constructor, + /// A destructor. + Destructor, + /// A virtual destructor. + VirtualDestructor { + /// Whether it's pure virtual. + pure_virtual: bool, + }, + /// A static method. + Static, + /// A normal method. + Normal, + /// A virtual method. + Virtual { + /// Whether it's pure virtual. + pure_virtual: bool, + }, +} + +impl MethodKind { + /// Is this a destructor method? + pub(crate) fn is_destructor(self) -> bool { + matches!( + self, + MethodKind::Destructor | MethodKind::VirtualDestructor { .. } + ) + } + + /// Is this a pure virtual method? + pub(crate) fn is_pure_virtual(self) -> bool { + match self { + MethodKind::Virtual { pure_virtual } | + MethodKind::VirtualDestructor { pure_virtual } => pure_virtual, + _ => false, + } + } +} + +/// A struct representing a C++ method, either static, normal, or virtual. +#[derive(Debug)] +pub(crate) struct Method { + kind: MethodKind, + /// The signature of the method. Take into account this is not a `Type` + /// item, but a `Function` one. + /// + /// This is tricky and probably this field should be renamed. + signature: FunctionId, + is_const: bool, +} + +impl Method { + /// Construct a new `Method`. + pub(crate) fn new( + kind: MethodKind, + signature: FunctionId, + is_const: bool, + ) -> Self { + Method { + kind, + signature, + is_const, + } + } + + /// What kind of method is this? + pub(crate) fn kind(&self) -> MethodKind { + self.kind + } + + /// Is this a constructor? + pub(crate) fn is_constructor(&self) -> bool { + self.kind == MethodKind::Constructor + } + + /// Is this a virtual method? + pub(crate) fn is_virtual(&self) -> bool { + matches!( + self.kind, + MethodKind::Virtual { .. } | MethodKind::VirtualDestructor { .. } + ) + } + + /// Is this a static method? + pub(crate) fn is_static(&self) -> bool { + self.kind == MethodKind::Static + } + + /// Get the ID for the `Function` signature for this method. + pub(crate) fn signature(&self) -> FunctionId { + self.signature + } + + /// Is this a const qualified method? + pub(crate) fn is_const(&self) -> bool { + self.is_const + } +} + +/// Methods common to the various field types. +pub(crate) trait FieldMethods { + /// Get the name of this field. + fn name(&self) -> Option<&str>; + + /// Get the type of this field. + fn ty(&self) -> TypeId; + + /// Get the comment for this field. + fn comment(&self) -> Option<&str>; + + /// If this is a bitfield, how many bits does it need? + fn bitfield_width(&self) -> Option; + + /// Is this field declared public? + fn is_public(&self) -> bool; + + /// Get the annotations for this field. + fn annotations(&self) -> &Annotations; + + /// The offset of the field (in bits) + fn offset(&self) -> Option; +} + +/// A contiguous set of logical bitfields that live within the same physical +/// allocation unit. See 9.2.4 [class.bit] in the C++ standard and [section +/// 2.4.II.1 in the Itanium C++ +/// ABI](http://itanium-cxx-abi.github.io/cxx-abi/abi.html#class-types). +#[derive(Debug)] +pub(crate) struct BitfieldUnit { + nth: usize, + layout: Layout, + bitfields: Vec, +} + +impl BitfieldUnit { + /// Get the 1-based index of this bitfield unit within its containing + /// struct. Useful for generating a Rust struct's field name for this unit + /// of bitfields. + pub(crate) fn nth(&self) -> usize { + self.nth + } + + /// Get the layout within which these bitfields reside. + pub(crate) fn layout(&self) -> Layout { + self.layout + } + + /// Get the bitfields within this unit. + pub(crate) fn bitfields(&self) -> &[Bitfield] { + &self.bitfields + } +} + +/// A struct representing a C++ field. +#[derive(Debug)] +pub(crate) enum Field { + /// A normal data member. + DataMember(FieldData), + + /// A physical allocation unit containing many logical bitfields. + Bitfields(BitfieldUnit), +} + +impl Field { + /// Get this field's layout. + pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option { + match *self { + Field::Bitfields(BitfieldUnit { layout, .. }) => Some(layout), + Field::DataMember(ref data) => { + ctx.resolve_type(data.ty).layout(ctx) + } + } + } +} + +impl Trace for Field { + type Extra = (); + + fn trace(&self, _: &BindgenContext, tracer: &mut T, _: &()) + where + T: Tracer, + { + match *self { + Field::DataMember(ref data) => { + tracer.visit_kind(data.ty.into(), EdgeKind::Field); + } + Field::Bitfields(BitfieldUnit { ref bitfields, .. }) => { + for bf in bitfields { + tracer.visit_kind(bf.ty().into(), EdgeKind::Field); + } + } + } + } +} + +impl DotAttributes for Field { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + match *self { + Field::DataMember(ref data) => data.dot_attributes(ctx, out), + Field::Bitfields(BitfieldUnit { + layout, + ref bitfields, + .. + }) => { + writeln!( + out, + r#" + bitfield unit + + + + + + + + + "#, + layout.size, layout.align + )?; + for bf in bitfields { + bf.dot_attributes(ctx, out)?; + } + writeln!(out, "
unit.size{}
unit.align{}
") + } + } + } +} + +impl DotAttributes for FieldData { + fn dot_attributes( + &self, + _ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!( + out, + "{}{:?}", + self.name().unwrap_or("(anonymous)"), + self.ty() + ) + } +} + +impl DotAttributes for Bitfield { + fn dot_attributes( + &self, + _ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!( + out, + "{} : {}{:?}", + self.name().unwrap_or("(anonymous)"), + self.width(), + self.ty() + ) + } +} + +/// A logical bitfield within some physical bitfield allocation unit. +#[derive(Debug)] +pub(crate) struct Bitfield { + /// Index of the bit within this bitfield's allocation unit where this + /// bitfield's bits begin. + offset_into_unit: usize, + + /// The field data for this bitfield. + data: FieldData, + + /// Name of the generated Rust getter for this bitfield. + /// + /// Should be assigned before codegen. + getter_name: Option, + + /// Name of the generated Rust setter for this bitfield. + /// + /// Should be assigned before codegen. + setter_name: Option, +} + +impl Bitfield { + /// Construct a new bitfield. + fn new(offset_into_unit: usize, raw: RawField) -> Bitfield { + assert!(raw.bitfield_width().is_some()); + + Bitfield { + offset_into_unit, + data: raw.0, + getter_name: None, + setter_name: None, + } + } + + /// Get the index of the bit within this bitfield's allocation unit where + /// this bitfield begins. + pub(crate) fn offset_into_unit(&self) -> usize { + self.offset_into_unit + } + + /// Get the bit width of this bitfield. + pub(crate) fn width(&self) -> u32 { + self.data.bitfield_width().unwrap() + } + + /// Name of the generated Rust getter for this bitfield. + /// + /// Panics if called before assigning bitfield accessor names or if + /// this bitfield have no name. + pub(crate) fn getter_name(&self) -> &str { + assert!( + self.name().is_some(), + "`Bitfield::getter_name` called on anonymous field" + ); + self.getter_name.as_ref().expect( + "`Bitfield::getter_name` should only be called after \ + assigning bitfield accessor names", + ) + } + + /// Name of the generated Rust setter for this bitfield. + /// + /// Panics if called before assigning bitfield accessor names or if + /// this bitfield have no name. + pub(crate) fn setter_name(&self) -> &str { + assert!( + self.name().is_some(), + "`Bitfield::setter_name` called on anonymous field" + ); + self.setter_name.as_ref().expect( + "`Bitfield::setter_name` should only be called \ + after assigning bitfield accessor names", + ) + } +} + +impl FieldMethods for Bitfield { + fn name(&self) -> Option<&str> { + self.data.name() + } + + fn ty(&self) -> TypeId { + self.data.ty() + } + + fn comment(&self) -> Option<&str> { + self.data.comment() + } + + fn bitfield_width(&self) -> Option { + self.data.bitfield_width() + } + + fn is_public(&self) -> bool { + self.data.is_public() + } + + fn annotations(&self) -> &Annotations { + self.data.annotations() + } + + fn offset(&self) -> Option { + self.data.offset() + } +} + +/// A raw field might be either of a plain data member or a bitfield within a +/// bitfield allocation unit, but we haven't processed it and determined which +/// yet (which would involve allocating it into a bitfield unit if it is a +/// bitfield). +#[derive(Debug)] +struct RawField(FieldData); + +impl RawField { + /// Construct a new `RawField`. + fn new( + name: Option, + ty: TypeId, + comment: Option, + annotations: Option, + bitfield_width: Option, + public: bool, + offset: Option, + ) -> RawField { + RawField(FieldData { + name, + ty, + comment, + annotations: annotations.unwrap_or_default(), + bitfield_width, + public, + offset, + }) + } +} + +impl FieldMethods for RawField { + fn name(&self) -> Option<&str> { + self.0.name() + } + + fn ty(&self) -> TypeId { + self.0.ty() + } + + fn comment(&self) -> Option<&str> { + self.0.comment() + } + + fn bitfield_width(&self) -> Option { + self.0.bitfield_width() + } + + fn is_public(&self) -> bool { + self.0.is_public() + } + + fn annotations(&self) -> &Annotations { + self.0.annotations() + } + + fn offset(&self) -> Option { + self.0.offset() + } +} + +/// Convert the given ordered set of raw fields into a list of either plain data +/// members, and/or bitfield units containing multiple bitfields. +/// +/// If we do not have the layout for a bitfield's type, then we can't reliably +/// compute its allocation unit. In such cases, we return an error. +fn raw_fields_to_fields_and_bitfield_units( + ctx: &BindgenContext, + raw_fields: I, + packed: bool, +) -> Result<(Vec, bool), ()> +where + I: IntoIterator, +{ + let mut raw_fields = raw_fields.into_iter().fuse().peekable(); + let mut fields = vec![]; + let mut bitfield_unit_count = 0; + + loop { + // While we have plain old data members, just keep adding them to our + // resulting fields. We introduce a scope here so that we can use + // `raw_fields` again after the `by_ref` iterator adaptor is dropped. + { + let non_bitfields = raw_fields + .by_ref() + .peeking_take_while(|f| f.bitfield_width().is_none()) + .map(|f| Field::DataMember(f.0)); + fields.extend(non_bitfields); + } + + // Now gather all the consecutive bitfields. Only consecutive bitfields + // may potentially share a bitfield allocation unit with each other in + // the Itanium C++ ABI. + let mut bitfields = raw_fields + .by_ref() + .peeking_take_while(|f| f.bitfield_width().is_some()) + .peekable(); + + if bitfields.peek().is_none() { + break; + } + + bitfields_to_allocation_units( + ctx, + &mut bitfield_unit_count, + &mut fields, + bitfields, + packed, + )?; + } + + assert!( + raw_fields.next().is_none(), + "The above loop should consume all items in `raw_fields`" + ); + + Ok((fields, bitfield_unit_count != 0)) +} + +/// Given a set of contiguous raw bitfields, group and allocate them into +/// (potentially multiple) bitfield units. +fn bitfields_to_allocation_units( + ctx: &BindgenContext, + bitfield_unit_count: &mut usize, + fields: &mut E, + raw_bitfields: I, + packed: bool, +) -> Result<(), ()> +where + E: Extend, + I: IntoIterator, +{ + assert!(ctx.collected_typerefs()); + + // NOTE: What follows is reverse-engineered from LLVM's + // lib/AST/RecordLayoutBuilder.cpp + // + // FIXME(emilio): There are some differences between Microsoft and the + // Itanium ABI, but we'll ignore those and stick to Itanium for now. + // + // Also, we need to handle packed bitfields and stuff. + // + // TODO(emilio): Take into account C++'s wide bitfields, and + // packing, sigh. + + fn flush_allocation_unit( + fields: &mut E, + bitfield_unit_count: &mut usize, + unit_size_in_bits: usize, + bitfields: Vec, + ) where + E: Extend, + { + *bitfield_unit_count += 1; + let align = 1; + let size = align_to(unit_size_in_bits, 8) / 8; + let layout = Layout::new(size, align); + fields.extend(Some(Field::Bitfields(BitfieldUnit { + nth: *bitfield_unit_count, + layout, + bitfields, + }))); + } + + // The offset we're in inside the struct, if we know it (we might not know it in presence of + // templates). + let mut start_offset_in_struct = 0; + let mut max_align = 0; + let mut unit_size_in_bits = 0; + let mut bitfields_in_unit = vec![]; + + // TODO(emilio): Deal with ms_struct bitfield layout for MSVC? + for bitfield in raw_bitfields { + let bitfield_width = bitfield.bitfield_width().unwrap() as usize; + let bitfield_layout = + ctx.resolve_type(bitfield.ty()).layout(ctx).ok_or(())?; + let bitfield_align = bitfield_layout.align; + let bitfield_size = bitfield_layout.size; + + if unit_size_in_bits == 0 { + start_offset_in_struct = bitfield.offset().unwrap_or(0); + } + + let mut offset_in_struct = + bitfield.offset().unwrap_or(unit_size_in_bits); + + // A zero-width field serves as alignment / padding. + if !packed && + offset_in_struct != 0 && + (bitfield_width == 0 || + (offset_in_struct & (bitfield_align * 8 - 1)) + + bitfield_width > + bitfield_size * 8) + { + offset_in_struct = align_to(offset_in_struct, bitfield_align * 8); + } + + // According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not affect the + // alignment of a structure or union". This makes sense: such bit-fields are only used for + // padding, and we can't perform an un-aligned read of something we can't read because we + // can't even name it. + if bitfield.name().is_some() { + max_align = cmp::max(max_align, bitfield_align); + } + + // Always keep all bitfields around. While unnamed bitifields are used + // for padding (and usually not needed hereafter), large unnamed + // bitfields over their types size cause weird allocation size behavior from clang. + // Therefore, all bitfields needed to be kept around in order to check for this + // and make the struct opaque in this case + bitfields_in_unit.push(Bitfield::new( + offset_in_struct - start_offset_in_struct, + bitfield, + )); + unit_size_in_bits = + offset_in_struct - start_offset_in_struct + bitfield_width; + } + + if unit_size_in_bits != 0 { + // Flush the last allocation unit and its bitfields. + flush_allocation_unit( + fields, + bitfield_unit_count, + unit_size_in_bits, + bitfields_in_unit, + ); + } + + Ok(()) +} + +/// A compound structure's fields are initially raw, and have bitfields that +/// have not been grouped into allocation units. During this time, the fields +/// are mutable and we build them up during parsing. +/// +/// Then, once resolving typerefs is completed, we compute all structs' fields' +/// bitfield allocation units, and they remain frozen and immutable forever +/// after. +#[derive(Debug)] +enum CompFields { + Before(Vec), + After { + fields: Vec, + has_bitfield_units: bool, + }, + Error, +} + +impl Default for CompFields { + fn default() -> CompFields { + CompFields::Before(vec![]) + } +} + +impl CompFields { + fn append_raw_field(&mut self, raw: RawField) { + match *self { + CompFields::Before(ref mut raws) => { + raws.push(raw); + } + _ => { + panic!( + "Must not append new fields after computing bitfield allocation units" + ); + } + } + } + + fn compute_bitfield_units(&mut self, ctx: &BindgenContext, packed: bool) { + let raws = match *self { + CompFields::Before(ref mut raws) => mem::take(raws), + _ => { + panic!("Already computed bitfield units"); + } + }; + + let result = raw_fields_to_fields_and_bitfield_units(ctx, raws, packed); + + match result { + Ok((fields, has_bitfield_units)) => { + *self = CompFields::After { + fields, + has_bitfield_units, + }; + } + Err(()) => { + *self = CompFields::Error; + } + } + } + + fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) { + let fields = match *self { + CompFields::After { ref mut fields, .. } => fields, + // Nothing to do here. + CompFields::Error => return, + CompFields::Before(_) => { + panic!("Not yet computed bitfield units."); + } + }; + + fn has_method( + methods: &[Method], + ctx: &BindgenContext, + name: &str, + ) -> bool { + methods.iter().any(|method| { + let method_name = ctx.resolve_func(method.signature()).name(); + method_name == name || ctx.rust_mangle(method_name) == name + }) + } + + struct AccessorNamesPair { + getter: String, + setter: String, + } + + let mut accessor_names: HashMap = fields + .iter() + .flat_map(|field| match *field { + Field::Bitfields(ref bu) => &*bu.bitfields, + Field::DataMember(_) => &[], + }) + .filter_map(|bitfield| bitfield.name()) + .map(|bitfield_name| { + let bitfield_name = bitfield_name.to_string(); + let getter = { + let mut getter = + ctx.rust_mangle(&bitfield_name).to_string(); + if has_method(methods, ctx, &getter) { + getter.push_str("_bindgen_bitfield"); + } + getter + }; + let setter = { + let setter = format!("set_{bitfield_name}"); + let mut setter = ctx.rust_mangle(&setter).to_string(); + if has_method(methods, ctx, &setter) { + setter.push_str("_bindgen_bitfield"); + } + setter + }; + (bitfield_name, AccessorNamesPair { getter, setter }) + }) + .collect(); + + let mut anon_field_counter = 0; + for field in fields.iter_mut() { + match *field { + Field::DataMember(FieldData { ref mut name, .. }) => { + if name.is_some() { + continue; + } + + anon_field_counter += 1; + *name = Some(format!( + "{}{anon_field_counter}", + ctx.options().anon_fields_prefix, + )); + } + Field::Bitfields(ref mut bu) => { + for bitfield in &mut bu.bitfields { + if bitfield.name().is_none() { + continue; + } + + if let Some(AccessorNamesPair { getter, setter }) = + accessor_names.remove(bitfield.name().unwrap()) + { + bitfield.getter_name = Some(getter); + bitfield.setter_name = Some(setter); + } + } + } + } + } + } + + /// Return the flex array member for the struct/class, if any. + fn flex_array_member(&self, ctx: &BindgenContext) -> Option { + let fields = match self { + CompFields::Before(_) => panic!("raw fields"), + CompFields::After { fields, .. } => fields, + CompFields::Error => return None, // panic? + }; + + match fields.last()? { + Field::Bitfields(..) => None, + Field::DataMember(FieldData { ty, .. }) => ctx + .resolve_type(*ty) + .is_incomplete_array(ctx) + .map(|item| item.expect_type_id(ctx)), + } + } +} + +impl Trace for CompFields { + type Extra = (); + + fn trace(&self, context: &BindgenContext, tracer: &mut T, _: &()) + where + T: Tracer, + { + match *self { + CompFields::Error => {} + CompFields::Before(ref fields) => { + for f in fields { + tracer.visit_kind(f.ty().into(), EdgeKind::Field); + } + } + CompFields::After { ref fields, .. } => { + for f in fields { + f.trace(context, tracer, &()); + } + } + } + } +} + +/// Common data shared across different field types. +#[derive(Clone, Debug)] +pub(crate) struct FieldData { + /// The name of the field, empty if it's an unnamed bitfield width. + name: Option, + + /// The inner type. + ty: TypeId, + + /// The doc comment on the field if any. + comment: Option, + + /// Annotations for this field, or the default. + annotations: Annotations, + + /// If this field is a bitfield, and how many bits does it contain if it is. + bitfield_width: Option, + + /// If the C++ field is declared `public` + public: bool, + + /// The offset of the field (in bits) + offset: Option, +} + +impl FieldMethods for FieldData { + fn name(&self) -> Option<&str> { + self.name.as_deref() + } + + fn ty(&self) -> TypeId { + self.ty + } + + fn comment(&self) -> Option<&str> { + self.comment.as_deref() + } + + fn bitfield_width(&self) -> Option { + self.bitfield_width + } + + fn is_public(&self) -> bool { + self.public + } + + fn annotations(&self) -> &Annotations { + &self.annotations + } + + fn offset(&self) -> Option { + self.offset + } +} + +/// The kind of inheritance a base class is using. +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) enum BaseKind { + /// Normal inheritance, like: + /// + /// ```cpp + /// class A : public B {}; + /// ``` + Normal, + /// Virtual inheritance, like: + /// + /// ```cpp + /// class A: public virtual B {}; + /// ``` + Virtual, +} + +/// A base class. +#[derive(Clone, Debug)] +pub(crate) struct Base { + /// The type of this base class. + pub(crate) ty: TypeId, + /// The kind of inheritance we're doing. + pub(crate) kind: BaseKind, + /// Name of the field in which this base should be stored. + pub(crate) field_name: String, + /// Whether this base is inherited from publicly. + pub(crate) is_pub: bool, +} + +impl Base { + /// Whether this base class is inheriting virtually. + pub(crate) fn is_virtual(&self) -> bool { + self.kind == BaseKind::Virtual + } + + /// Whether this base class should have it's own field for storage. + pub(crate) fn requires_storage(&self, ctx: &BindgenContext) -> bool { + // Virtual bases are already taken into account by the vtable + // pointer. + // + // FIXME(emilio): Is this always right? + if self.is_virtual() { + return false; + } + + // NB: We won't include zero-sized types in our base chain because they + // would contribute to our size given the dummy field we insert for + // zero-sized types. + if self.ty.is_zero_sized(ctx) { + return false; + } + + true + } + + /// Whether this base is inherited from publicly. + pub(crate) fn is_public(&self) -> bool { + self.is_pub + } +} + +/// A compound type. +/// +/// Either a struct or union, a compound type is built up from the combination +/// of fields which also are associated with their own (potentially compound) +/// type. +#[derive(Debug)] +pub(crate) struct CompInfo { + /// Whether this is a struct or a union. + kind: CompKind, + + /// The members of this struct or union. + fields: CompFields, + + /// The abstract template parameters of this class. Note that these are NOT + /// concrete template arguments, and should always be a + /// `Type(TypeKind::TypeParam(name))`. For concrete template arguments, see + /// `TypeKind::TemplateInstantiation`. + template_params: Vec, + + /// The method declarations inside this class, if in C++ mode. + methods: Vec, + + /// The different constructors this struct or class contains. + constructors: Vec, + + /// The destructor of this type. The bool represents whether this destructor + /// is virtual. + destructor: Option<(MethodKind, FunctionId)>, + + /// Vector of classes this one inherits from. + base_members: Vec, + + /// The inner types that were declared inside this class, in something like: + /// + /// ```c++ + /// class Foo { + /// typedef int FooTy; + /// struct Bar { + /// int baz; + /// }; + /// } + /// + /// static Foo::Bar const = {3}; + /// ``` + inner_types: Vec, + + /// Set of static constants declared inside this class. + inner_vars: Vec, + + /// Whether this type should generate an vtable (TODO: Should be able to + /// look at the virtual methods and ditch this field). + has_own_virtual_method: bool, + + /// Whether this type has destructor. + has_destructor: bool, + + /// Whether this type has a base type with more than one member. + /// + /// TODO: We should be able to compute this. + has_nonempty_base: bool, + + /// If this type has a template parameter which is not a type (e.g.: a + /// `size_t`) + has_non_type_template_params: bool, + + /// Whether this type has a bit field member whose width couldn't be + /// evaluated (e.g. if it depends on a template parameter). We generate an + /// opaque type in this case. + has_unevaluable_bit_field_width: bool, + + /// Whether we saw `__attribute__((packed))` on or within this type. + packed_attr: bool, + + /// Used to know if we've found an opaque attribute that could cause us to + /// generate a type with invalid layout. This is explicitly used to avoid us + /// generating bad alignments when parsing types like `max_align_t`. + /// + /// It's not clear what the behavior should be here, if generating the item + /// and pray, or behave as an opaque type. + found_unknown_attr: bool, + + /// Used to indicate when a struct has been forward declared. Usually used + /// in headers so that APIs can't modify them directly. + is_forward_declaration: bool, +} + +impl CompInfo { + /// Construct a new compound type. + pub(crate) fn new(kind: CompKind) -> Self { + CompInfo { + kind, + fields: CompFields::default(), + template_params: vec![], + methods: vec![], + constructors: vec![], + destructor: None, + base_members: vec![], + inner_types: vec![], + inner_vars: vec![], + has_own_virtual_method: false, + has_destructor: false, + has_nonempty_base: false, + has_non_type_template_params: false, + has_unevaluable_bit_field_width: false, + packed_attr: false, + found_unknown_attr: false, + is_forward_declaration: false, + } + } + + /// Compute the layout of this type. + /// + /// This is called as a fallback under some circumstances where LLVM doesn't + /// give us the correct layout. + /// + /// If we're a union without known layout, we try to compute it from our + /// members. This is not ideal, but clang fails to report the size for these + /// kind of unions, see `test/headers/template_union.hpp` + pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option { + // We can't do better than clang here, sorry. + if self.kind == CompKind::Struct { + return None; + } + + // By definition, we don't have the right layout information here if + // we're a forward declaration. + if self.is_forward_declaration() { + return None; + } + + // empty union case + if !self.has_fields() { + return None; + } + + let mut max_size = 0; + // Don't allow align(0) + let mut max_align = 1; + self.each_known_field_layout(ctx, |layout| { + max_size = cmp::max(max_size, layout.size); + max_align = cmp::max(max_align, layout.align); + }); + + Some(Layout::new(max_size, max_align)) + } + + /// Get this type's set of fields. + pub(crate) fn fields(&self) -> &[Field] { + match self.fields { + CompFields::Error => &[], + CompFields::After { ref fields, .. } => fields, + CompFields::Before(..) => { + panic!("Should always have computed bitfield units first"); + } + } + } + + /// Return the flex array member and its element type if any + pub(crate) fn flex_array_member( + &self, + ctx: &BindgenContext, + ) -> Option { + self.fields.flex_array_member(ctx) + } + + fn has_fields(&self) -> bool { + match self.fields { + CompFields::Error => false, + CompFields::After { ref fields, .. } => !fields.is_empty(), + CompFields::Before(ref raw_fields) => !raw_fields.is_empty(), + } + } + + fn each_known_field_layout( + &self, + ctx: &BindgenContext, + mut callback: impl FnMut(Layout), + ) { + match self.fields { + CompFields::Error => {} + CompFields::After { ref fields, .. } => { + for field in fields { + if let Some(layout) = field.layout(ctx) { + callback(layout); + } + } + } + CompFields::Before(ref raw_fields) => { + for field in raw_fields { + let field_ty = ctx.resolve_type(field.0.ty); + if let Some(layout) = field_ty.layout(ctx) { + callback(layout); + } + } + } + } + } + + /// Returns whether we have any bitfield within the struct. + pub(crate) fn has_bitfields(&self) -> bool { + match self.fields { + CompFields::Error => false, + CompFields::After { + has_bitfield_units, .. + } => has_bitfield_units, + CompFields::Before(_) => { + panic!("Should always have computed bitfield units first"); + } + } + } + + /// Returns whether we have a too large bitfield unit, in which case we may + /// not be able to derive some of the things we should be able to normally + /// derive. + pub(crate) fn has_too_large_bitfield_unit(&self) -> bool { + if !self.has_bitfields() { + return false; + } + self.fields().iter().any(|field| match *field { + Field::DataMember(..) => false, + Field::Bitfields(ref unit) => { + unit.layout.size > RUST_DERIVE_IN_ARRAY_LIMIT + } + }) + } + + /// Does this type have any template parameters that aren't types + /// (e.g. int)? + pub(crate) fn has_non_type_template_params(&self) -> bool { + self.has_non_type_template_params + } + + /// Do we see a virtual function during parsing? + /// Get the `has_own_virtual_method` boolean. + pub(crate) fn has_own_virtual_method(&self) -> bool { + self.has_own_virtual_method + } + + /// Did we see a destructor when parsing this type? + pub(crate) fn has_own_destructor(&self) -> bool { + self.has_destructor + } + + /// Get this type's set of methods. + pub(crate) fn methods(&self) -> &[Method] { + &self.methods + } + + /// Get this type's set of constructors. + pub(crate) fn constructors(&self) -> &[FunctionId] { + &self.constructors + } + + /// Get this type's destructor. + pub(crate) fn destructor(&self) -> Option<(MethodKind, FunctionId)> { + self.destructor + } + + /// What kind of compound type is this? + pub(crate) fn kind(&self) -> CompKind { + self.kind + } + + /// Is this a union? + pub(crate) fn is_union(&self) -> bool { + self.kind() == CompKind::Union + } + + /// The set of types that this one inherits from. + pub(crate) fn base_members(&self) -> &[Base] { + &self.base_members + } + + /// Construct a new compound type from a Clang type. + pub(crate) fn from_ty( + potential_id: ItemId, + ty: &clang::Type, + location: Option, + ctx: &mut BindgenContext, + ) -> Result { + use clang_sys::*; + assert!( + ty.template_args().is_none(), + "We handle template instantiations elsewhere" + ); + + let mut cursor = ty.declaration(); + let mut kind = Self::kind_from_cursor(&cursor); + if kind.is_err() { + if let Some(location) = location { + kind = Self::kind_from_cursor(&location); + cursor = location; + } + } + + let kind = kind?; + + debug!("CompInfo::from_ty({kind:?}, {cursor:?})"); + + let mut ci = CompInfo::new(kind); + ci.is_forward_declaration = + location.map_or(true, |cur| match cur.kind() { + CXCursor_ParmDecl => true, + CXCursor_StructDecl | CXCursor_UnionDecl | + CXCursor_ClassDecl => !cur.is_definition(), + _ => false, + }); + + let mut maybe_anonymous_struct_field = None; + cursor.visit(|cur| { + if cur.kind() != CXCursor_FieldDecl { + if let Some((ty, clang_ty, public, offset)) = + maybe_anonymous_struct_field.take() + { + if cur.kind() == CXCursor_TypedefDecl && + cur.typedef_type().unwrap().canonical_type() == + clang_ty + { + // Typedefs of anonymous structs appear later in the ast + // than the struct itself, that would otherwise be an + // anonymous field. Detect that case here, and do + // nothing. + } else { + let field = RawField::new( + None, ty, None, None, None, public, offset, + ); + ci.fields.append_raw_field(field); + } + } + } + + match cur.kind() { + CXCursor_FieldDecl => { + if let Some((ty, clang_ty, public, offset)) = + maybe_anonymous_struct_field.take() + { + let mut used = false; + cur.visit(|child| { + if child.cur_type() == clang_ty { + used = true; + } + CXChildVisit_Continue + }); + + if !used { + let field = RawField::new( + None, ty, None, None, None, public, offset, + ); + ci.fields.append_raw_field(field); + } + } + + let bit_width = if cur.is_bit_field() { + let width = cur.bit_width(); + + // Make opaque type if the bit width couldn't be + // evaluated. + if width.is_none() { + ci.has_unevaluable_bit_field_width = true; + return CXChildVisit_Break; + } + + width + } else { + None + }; + + let field_type = Item::from_ty_or_ref( + cur.cur_type(), + cur, + Some(potential_id), + ctx, + ); + + let comment = cur.raw_comment(); + let annotations = Annotations::new(&cur); + let name = cur.spelling(); + let is_public = cur.public_accessible(); + let offset = cur.offset_of_field().ok(); + + // Name can be empty if there are bitfields, for example, + // see tests/headers/struct_with_bitfields.h + assert!( + !name.is_empty() || bit_width.is_some(), + "Empty field name?" + ); + + let name = if name.is_empty() { None } else { Some(name) }; + + let field = RawField::new( + name, + field_type, + comment, + annotations, + bit_width, + is_public, + offset, + ); + ci.fields.append_raw_field(field); + + // No we look for things like attributes and stuff. + cur.visit(|cur| { + if cur.kind() == CXCursor_UnexposedAttr { + ci.found_unknown_attr = true; + } + CXChildVisit_Continue + }); + } + CXCursor_UnexposedAttr => { + ci.found_unknown_attr = true; + } + CXCursor_EnumDecl | + CXCursor_TypeAliasDecl | + CXCursor_TypeAliasTemplateDecl | + CXCursor_TypedefDecl | + CXCursor_StructDecl | + CXCursor_UnionDecl | + CXCursor_ClassTemplate | + CXCursor_ClassDecl => { + // We can find non-semantic children here, clang uses a + // StructDecl to note incomplete structs that haven't been + // forward-declared before, see [1]. + // + // Also, clang seems to scope struct definitions inside + // unions, and other named struct definitions inside other + // structs to the whole translation unit. + // + // Let's just assume that if the cursor we've found is a + // definition, it's a valid inner type. + // + // [1]: https://github.com/rust-lang/rust-bindgen/issues/482 + let is_inner_struct = + cur.semantic_parent() == cursor || cur.is_definition(); + if !is_inner_struct { + return CXChildVisit_Continue; + } + + // Even if this is a definition, we may not be the semantic + // parent, see #1281. + let inner = Item::parse(cur, Some(potential_id), ctx) + .expect("Inner ClassDecl"); + + // If we avoided recursion parsing this type (in + // `Item::from_ty_with_id()`), then this might not be a + // valid type ID, so check and gracefully handle this. + if ctx.resolve_item_fallible(inner).is_some() { + let inner = inner.expect_type_id(ctx); + + ci.inner_types.push(inner); + + // A declaration of an union or a struct without name + // could also be an unnamed field, unfortunately. + if cur.is_anonymous() && cur.kind() != CXCursor_EnumDecl + { + let ty = cur.cur_type(); + let public = cur.public_accessible(); + let offset = cur.offset_of_field().ok(); + + maybe_anonymous_struct_field = + Some((inner, ty, public, offset)); + } + } + } + CXCursor_PackedAttr => { + ci.packed_attr = true; + } + CXCursor_TemplateTypeParameter => { + let param = Item::type_param(None, cur, ctx).expect( + "Item::type_param shouldn't fail when pointing \ + at a TemplateTypeParameter", + ); + ci.template_params.push(param); + } + CXCursor_CXXBaseSpecifier => { + let is_virtual_base = cur.is_virtual_base(); + ci.has_own_virtual_method |= is_virtual_base; + + let kind = if is_virtual_base { + BaseKind::Virtual + } else { + BaseKind::Normal + }; + + let field_name = match ci.base_members.len() { + 0 => "_base".into(), + n => format!("_base_{n}"), + }; + let type_id = + Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx); + ci.base_members.push(Base { + ty: type_id, + kind, + field_name, + is_pub: cur.access_specifier() == CX_CXXPublic, + }); + } + CXCursor_Constructor | CXCursor_Destructor | + CXCursor_CXXMethod => { + let is_virtual = cur.method_is_virtual(); + let is_static = cur.method_is_static(); + debug_assert!(!(is_static && is_virtual), "How?"); + + ci.has_destructor |= cur.kind() == CXCursor_Destructor; + ci.has_own_virtual_method |= is_virtual; + + // This used to not be here, but then I tried generating + // stylo bindings with this (without path filters), and + // cried a lot with a method in gfx/Point.h + // (ToUnknownPoint), that somehow was causing the same type + // to be inserted in the map two times. + // + // I couldn't make a reduced test case, but anyway... + // Methods of template functions not only used to be inlined, + // but also instantiated, and we wouldn't be able to call + // them, so just bail out. + if !ci.template_params.is_empty() { + return CXChildVisit_Continue; + } + + // NB: This gets us an owned `Function`, not a + // `FunctionSig`. + let signature = + match Item::parse(cur, Some(potential_id), ctx) { + Ok(item) + if ctx + .resolve_item(item) + .kind() + .is_function() => + { + item + } + _ => return CXChildVisit_Continue, + }; + + let signature = signature.expect_function_id(ctx); + + match cur.kind() { + CXCursor_Constructor => { + ci.constructors.push(signature); + } + CXCursor_Destructor => { + let kind = if is_virtual { + MethodKind::VirtualDestructor { + pure_virtual: cur.method_is_pure_virtual(), + } + } else { + MethodKind::Destructor + }; + ci.destructor = Some((kind, signature)); + } + CXCursor_CXXMethod => { + let is_const = cur.method_is_const(); + let method_kind = if is_static { + MethodKind::Static + } else if is_virtual { + MethodKind::Virtual { + pure_virtual: cur.method_is_pure_virtual(), + } + } else { + MethodKind::Normal + }; + + let method = + Method::new(method_kind, signature, is_const); + + ci.methods.push(method); + } + _ => unreachable!("How can we see this here?"), + } + } + CXCursor_NonTypeTemplateParameter => { + ci.has_non_type_template_params = true; + } + CXCursor_VarDecl => { + let linkage = cur.linkage(); + if linkage != CXLinkage_External && + linkage != CXLinkage_UniqueExternal + { + return CXChildVisit_Continue; + } + + let visibility = cur.visibility(); + if visibility != CXVisibility_Default { + return CXChildVisit_Continue; + } + + if let Ok(item) = Item::parse(cur, Some(potential_id), ctx) + { + ci.inner_vars.push(item.as_var_id_unchecked()); + } + } + // Intentionally not handled + CXCursor_CXXAccessSpecifier | + CXCursor_CXXFinalAttr | + CXCursor_FunctionTemplate | + CXCursor_ConversionFunction => {} + _ => { + warn!( + "unhandled comp member `{}` (kind {:?}) in `{}` ({})", + cur.spelling(), + clang::kind_to_str(cur.kind()), + cursor.spelling(), + cur.location() + ); + } + } + CXChildVisit_Continue + }); + + if let Some((ty, _, public, offset)) = maybe_anonymous_struct_field { + let field = + RawField::new(None, ty, None, None, None, public, offset); + ci.fields.append_raw_field(field); + } + + Ok(ci) + } + + fn kind_from_cursor( + cursor: &clang::Cursor, + ) -> Result { + use clang_sys::*; + Ok(match cursor.kind() { + CXCursor_UnionDecl => CompKind::Union, + CXCursor_ClassDecl | CXCursor_StructDecl => CompKind::Struct, + CXCursor_CXXBaseSpecifier | + CXCursor_ClassTemplatePartialSpecialization | + CXCursor_ClassTemplate => match cursor.template_kind() { + CXCursor_UnionDecl => CompKind::Union, + _ => CompKind::Struct, + }, + _ => { + warn!("Unknown kind for comp type: {cursor:?}"); + return Err(ParseError::Continue); + } + }) + } + + /// Get the set of types that were declared within this compound type + /// (e.g. nested class definitions). + pub(crate) fn inner_types(&self) -> &[TypeId] { + &self.inner_types + } + + /// Get the set of static variables declared within this compound type. + pub(crate) fn inner_vars(&self) -> &[VarId] { + &self.inner_vars + } + + /// Have we found a field with an opaque type that could potentially mess up + /// the layout of this compound type? + pub(crate) fn found_unknown_attr(&self) -> bool { + self.found_unknown_attr + } + + /// Is this compound type packed? + pub(crate) fn is_packed( + &self, + ctx: &BindgenContext, + layout: Option<&Layout>, + ) -> bool { + if self.packed_attr { + return true; + } + + // Even though `libclang` doesn't expose `#pragma packed(...)`, we can + // detect it through its effects. + if let Some(parent_layout) = layout { + let mut packed = false; + self.each_known_field_layout(ctx, |layout| { + packed = packed || layout.align > parent_layout.align; + }); + if packed { + info!("Found a struct that was defined within `#pragma packed(...)`"); + return true; + } + + if self.has_own_virtual_method && parent_layout.align == 1 { + return true; + } + } + + false + } + + /// Return true if a compound type is "naturally packed". This means we can exclude the + /// "packed" attribute without changing the layout. + /// This is useful for types that need an "align(N)" attribute since rustc won't compile + /// structs that have both of those attributes. + pub(crate) fn already_packed(&self, ctx: &BindgenContext) -> Option { + let mut total_size: usize = 0; + + for field in self.fields() { + let layout = field.layout(ctx)?; + + if layout.align != 0 && total_size % layout.align != 0 { + return Some(false); + } + + total_size += layout.size; + } + + Some(true) + } + + /// Returns true if compound type has been forward declared + pub(crate) fn is_forward_declaration(&self) -> bool { + self.is_forward_declaration + } + + /// Compute this compound structure's bitfield allocation units. + pub(crate) fn compute_bitfield_units( + &mut self, + ctx: &BindgenContext, + layout: Option<&Layout>, + ) { + let packed = self.is_packed(ctx, layout); + self.fields.compute_bitfield_units(ctx, packed); + } + + /// Assign for each anonymous field a generated name. + pub(crate) fn deanonymize_fields(&mut self, ctx: &BindgenContext) { + self.fields.deanonymize_fields(ctx, &self.methods); + } + + /// Returns whether the current union can be represented as a Rust `union` + /// + /// Requirements: + /// 1. Current `RustTarget` allows for `untagged_union` + /// 2. Each field can derive `Copy` or we use `ManuallyDrop`. + /// 3. It's not zero-sized. + /// + /// Second boolean returns whether all fields can be copied (and thus + /// `ManuallyDrop` is not needed). + pub(crate) fn is_rust_union( + &self, + ctx: &BindgenContext, + layout: Option<&Layout>, + name: &str, + ) -> (bool, bool) { + if !self.is_union() { + return (false, false); + } + + if !ctx.options().untagged_union { + return (false, false); + } + + if self.is_forward_declaration() { + return (false, false); + } + + let union_style = if ctx.options().bindgen_wrapper_union.matches(name) { + NonCopyUnionStyle::BindgenWrapper + } else if ctx.options().manually_drop_union.matches(name) { + NonCopyUnionStyle::ManuallyDrop + } else { + ctx.options().default_non_copy_union_style + }; + + let all_can_copy = self.fields().iter().all(|f| match *f { + Field::DataMember(ref field_data) => { + field_data.ty().can_derive_copy(ctx) + } + Field::Bitfields(_) => true, + }); + + if !all_can_copy && union_style == NonCopyUnionStyle::BindgenWrapper { + return (false, false); + } + + if layout.is_some_and(|l| l.size == 0) { + return (false, false); + } + + (true, all_can_copy) + } +} + +impl DotAttributes for CompInfo { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!(out, "CompKind{:?}", self.kind)?; + + if self.has_own_virtual_method { + writeln!(out, "has_vtabletrue")?; + } + + if self.has_destructor { + writeln!(out, "has_destructortrue")?; + } + + if self.has_nonempty_base { + writeln!(out, "has_nonempty_basetrue")?; + } + + if self.has_non_type_template_params { + writeln!( + out, + "has_non_type_template_paramstrue" + )?; + } + + if self.packed_attr { + writeln!(out, "packed_attrtrue")?; + } + + if self.is_forward_declaration { + writeln!( + out, + "is_forward_declarationtrue" + )?; + } + + if !self.fields().is_empty() { + writeln!(out, r#"fields"#)?; + for field in self.fields() { + field.dot_attributes(ctx, out)?; + } + writeln!(out, "
")?; + } + + Ok(()) + } +} + +impl IsOpaque for CompInfo { + type Extra = Option; + + fn is_opaque( + &self, + ctx: &BindgenContext, + _layout: &Option, + ) -> bool { + if self.has_non_type_template_params || + self.has_unevaluable_bit_field_width + { + return true; + } + + // When we do not have the layout for a bitfield's type (for example, it + // is a type parameter), then we can't compute bitfield units. We are + // left with no choice but to make the whole struct opaque, or else we + // might generate structs with incorrect sizes and alignments. + if let CompFields::Error = self.fields { + return true; + } + + // Bitfields with a width that is larger than their unit's width have + // some strange things going on, and the best we can do is make the + // whole struct opaque. + if self.fields().iter().any(|f| match *f { + Field::DataMember(_) => false, + Field::Bitfields(ref unit) => unit.bitfields().iter().any(|bf| { + let bitfield_layout = ctx + .resolve_type(bf.ty()) + .layout(ctx) + .expect("Bitfield without layout? Gah!"); + bf.width() / 8 > bitfield_layout.size as u32 + }), + }) { + return true; + } + + false + } +} + +impl TemplateParameters for CompInfo { + fn self_template_params(&self, _ctx: &BindgenContext) -> Vec { + self.template_params.clone() + } +} + +impl Trace for CompInfo { + type Extra = Item; + + fn trace(&self, context: &BindgenContext, tracer: &mut T, item: &Item) + where + T: Tracer, + { + for p in item.all_template_params(context) { + tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition); + } + + for ty in self.inner_types() { + tracer.visit_kind(ty.into(), EdgeKind::InnerType); + } + + for &var in self.inner_vars() { + tracer.visit_kind(var.into(), EdgeKind::InnerVar); + } + + for method in self.methods() { + tracer.visit_kind(method.signature.into(), EdgeKind::Method); + } + + if let Some((_kind, signature)) = self.destructor() { + tracer.visit_kind(signature.into(), EdgeKind::Destructor); + } + + for ctor in self.constructors() { + tracer.visit_kind(ctor.into(), EdgeKind::Constructor); + } + + // Base members and fields are not generated for opaque types (but all + // of the above things are) so stop here. + if item.is_opaque(context, &()) { + return; + } + + for base in self.base_members() { + tracer.visit_kind(base.ty.into(), EdgeKind::BaseMember); + } + + self.fields.trace(context, tracer, &()); + } +} diff --git a/bindgen/ir/context.rs b/bindgen/ir/context.rs new file mode 100644 index 0000000000..346d2932f7 --- /dev/null +++ b/bindgen/ir/context.rs @@ -0,0 +1,3113 @@ +//! Common context that is passed around during parsing and codegen. + +use super::super::time::Timer; +use super::analysis::{ + analyze, as_cannot_derive_set, CannotDerive, DeriveTrait, + HasDestructorAnalysis, HasFloat, HasTypeParameterInArray, + HasVtableAnalysis, HasVtableResult, SizednessAnalysis, SizednessResult, + UsedTemplateParameters, +}; +use super::derive::{ + CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq, + CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd, +}; +use super::function::Function; +use super::int::IntKind; +use super::item::{IsOpaque, Item, ItemAncestors, ItemSet}; +use super::item_kind::ItemKind; +use super::module::{Module, ModuleKind}; +use super::template::{TemplateInstantiation, TemplateParameters}; +use super::traversal::{self, Edge, ItemTraversal}; +use super::ty::{FloatKind, Type, TypeKind}; +use crate::clang::{self, ABIKind, Cursor}; +use crate::codegen::CodegenError; +use crate::BindgenOptions; +use crate::{Entry, HashMap, HashSet}; + +use proc_macro2::{Ident, Span, TokenStream}; +use quote::ToTokens; +use std::borrow::Cow; +use std::cell::{Cell, RefCell}; +use std::collections::{BTreeSet, HashMap as StdHashMap}; +use std::mem; +use std::path::Path; + +/// An identifier for some kind of IR item. +#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct ItemId(usize); + +/// Declare a newtype around `ItemId` with conversion methods. +macro_rules! item_id_newtype { + ( + $( #[$attr:meta] )* + pub(crate) struct $name:ident(ItemId) + where + $( #[$checked_attr:meta] )* + checked = $checked:ident with $check_method:ident, + $( #[$expected_attr:meta] )* + expected = $expected:ident, + $( #[$unchecked_attr:meta] )* + unchecked = $unchecked:ident; + ) => { + $( #[$attr] )* + #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)] + pub(crate) struct $name(ItemId); + + impl $name { + /// Create an `ItemResolver` from this ID. + #[allow(dead_code)] + pub(crate) fn into_resolver(self) -> ItemResolver { + let id: ItemId = self.into(); + id.into() + } + } + + impl ::std::cmp::PartialEq for $name + where + T: Copy + Into + { + fn eq(&self, rhs: &T) -> bool { + let rhs: ItemId = (*rhs).into(); + self.0 == rhs + } + } + + impl From<$name> for ItemId { + fn from(id: $name) -> ItemId { + id.0 + } + } + + impl<'a> From<&'a $name> for ItemId { + fn from(id: &'a $name) -> ItemId { + id.0 + } + } + + #[allow(dead_code)] + impl ItemId { + $( #[$checked_attr] )* + pub(crate) fn $checked(&self, ctx: &BindgenContext) -> Option<$name> { + if ctx.resolve_item(*self).kind().$check_method() { + Some($name(*self)) + } else { + None + } + } + + $( #[$expected_attr] )* + pub(crate) fn $expected(&self, ctx: &BindgenContext) -> $name { + self.$checked(ctx) + .expect(concat!( + stringify!($expected), + " called with ItemId that points to the wrong ItemKind" + )) + } + + $( #[$unchecked_attr] )* + pub(crate) fn $unchecked(&self) -> $name { + $name(*self) + } + } + } +} + +item_id_newtype! { + /// An identifier for an `Item` whose `ItemKind` is known to be + /// `ItemKind::Type`. + pub(crate) struct TypeId(ItemId) + where + /// Convert this `ItemId` into a `TypeId` if its associated item is a type, + /// otherwise return `None`. + checked = as_type_id with is_type, + + /// Convert this `ItemId` into a `TypeId`. + /// + /// If this `ItemId` does not point to a type, then panic. + expected = expect_type_id, + + /// Convert this `ItemId` into a `TypeId` without actually checking whether + /// this ID actually points to a `Type`. + unchecked = as_type_id_unchecked; +} + +item_id_newtype! { + /// An identifier for an `Item` whose `ItemKind` is known to be + /// `ItemKind::Module`. + pub(crate) struct ModuleId(ItemId) + where + /// Convert this `ItemId` into a `ModuleId` if its associated item is a + /// module, otherwise return `None`. + checked = as_module_id with is_module, + + /// Convert this `ItemId` into a `ModuleId`. + /// + /// If this `ItemId` does not point to a module, then panic. + expected = expect_module_id, + + /// Convert this `ItemId` into a `ModuleId` without actually checking + /// whether this ID actually points to a `Module`. + unchecked = as_module_id_unchecked; +} + +item_id_newtype! { + /// An identifier for an `Item` whose `ItemKind` is known to be + /// `ItemKind::Var`. + pub(crate) struct VarId(ItemId) + where + /// Convert this `ItemId` into a `VarId` if its associated item is a var, + /// otherwise return `None`. + checked = as_var_id with is_var, + + /// Convert this `ItemId` into a `VarId`. + /// + /// If this `ItemId` does not point to a var, then panic. + expected = expect_var_id, + + /// Convert this `ItemId` into a `VarId` without actually checking whether + /// this ID actually points to a `Var`. + unchecked = as_var_id_unchecked; +} + +item_id_newtype! { + /// An identifier for an `Item` whose `ItemKind` is known to be + /// `ItemKind::Function`. + pub(crate) struct FunctionId(ItemId) + where + /// Convert this `ItemId` into a `FunctionId` if its associated item is a function, + /// otherwise return `None`. + checked = as_function_id with is_function, + + /// Convert this `ItemId` into a `FunctionId`. + /// + /// If this `ItemId` does not point to a function, then panic. + expected = expect_function_id, + + /// Convert this `ItemId` into a `FunctionId` without actually checking whether + /// this ID actually points to a `Function`. + unchecked = as_function_id_unchecked; +} + +impl From for usize { + fn from(id: ItemId) -> usize { + id.0 + } +} + +impl ItemId { + /// Get a numeric representation of this ID. + pub(crate) fn as_usize(self) -> usize { + self.into() + } +} + +impl ::std::cmp::PartialEq for ItemId +where + T: Copy + Into, +{ + fn eq(&self, rhs: &T) -> bool { + let rhs: ItemId = (*rhs).into(); + self.0 == rhs.0 + } +} + +impl CanDeriveDebug for T +where + T: Copy + Into, +{ + fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self) + } +} + +impl CanDeriveDefault for T +where + T: Copy + Into, +{ + fn can_derive_default(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_default && ctx.lookup_can_derive_default(*self) + } +} + +impl CanDeriveCopy for T +where + T: Copy + Into, +{ + fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self) + } +} + +impl CanDeriveHash for T +where + T: Copy + Into, +{ + fn can_derive_hash(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self) + } +} + +impl CanDerivePartialOrd for T +where + T: Copy + Into, +{ + fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_partialord && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == + CanDerive::Yes + } +} + +impl CanDerivePartialEq for T +where + T: Copy + Into, +{ + fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_partialeq && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == + CanDerive::Yes + } +} + +impl CanDeriveEq for T +where + T: Copy + Into, +{ + fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_eq && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == + CanDerive::Yes && + !ctx.lookup_has_float(*self) + } +} + +impl CanDeriveOrd for T +where + T: Copy + Into, +{ + fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_ord && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == + CanDerive::Yes && + !ctx.lookup_has_float(*self) + } +} + +/// A key used to index a resolved type, so we only process it once. +/// +/// This is almost always a USR string (an unique identifier generated by +/// clang), but it can also be the canonical declaration if the type is unnamed, +/// in which case clang may generate the same USR for multiple nested unnamed +/// types. +#[derive(Eq, PartialEq, Hash, Debug)] +enum TypeKey { + Usr(String), + Declaration(Cursor), +} + +/// A context used during parsing and generation of structs. +#[derive(Debug)] +pub(crate) struct BindgenContext { + /// The map of all the items parsed so far, keyed off `ItemId`. + items: Vec>, + + /// Clang USR to type map. This is needed to be able to associate types with + /// item ids during parsing. + types: HashMap, + + /// Maps from a cursor to the item ID of the named template type parameter + /// for that cursor. + type_params: HashMap, + + /// A cursor to module map. Similar reason than above. + modules: HashMap, + + /// The root module, this is guaranteed to be an item of kind Module. + root_module: ModuleId, + + /// Current module being traversed. + current_module: ModuleId, + + /// A `HashMap` keyed on a type definition, and whose value is the parent ID + /// of the declaration. + /// + /// This is used to handle the cases where the semantic and the lexical + /// parents of the cursor differ, like when a nested class is defined + /// outside of the parent class. + semantic_parents: HashMap, + + /// A stack with the current type declarations and types we're parsing. This + /// is needed to avoid infinite recursion when parsing a type like: + /// + /// struct c { struct c* next; }; + /// + /// This means effectively, that a type has a potential ID before knowing if + /// it's a correct type. But that's not important in practice. + /// + /// We could also use the `types` `HashMap`, but my intention with it is that + /// only valid types and declarations end up there, and this could + /// potentially break that assumption. + currently_parsed_types: Vec, + + /// A map with all the already parsed macro names. This is done to avoid + /// hard errors while parsing duplicated macros, as well to allow macro + /// expression parsing. + /// + /// This needs to be an `std::HashMap` because the `cexpr` API requires it. + parsed_macros: StdHashMap, cexpr::expr::EvalResult>, + + /// A map with all include locations. + /// + /// This is needed so that items are created in the order they are defined in. + /// + /// The key is the included file, the value is a pair of the source file and + /// the position of the `#include` directive in the source file. + includes: StdHashMap, + + /// A set of all the included filenames. + deps: BTreeSet>, + + /// The active replacements collected from replaces="xxx" annotations. + replacements: HashMap, ItemId>, + + collected_typerefs: bool, + + in_codegen: bool, + + /// The translation unit for parsing. + translation_unit: clang::TranslationUnit, + + /// The translation unit for macro fallback parsing. + fallback_tu: Option, + + /// Target information that can be useful for some stuff. + target_info: clang::TargetInfo, + + /// The options given by the user via cli or other medium. + options: BindgenOptions, + + /// Whether an opaque array was generated + generated_opaque_array: RefCell>, + + /// Whether a bindgen complex was generated + generated_bindgen_complex: Cell, + + /// Whether a bindgen float16 was generated + generated_bindgen_float16: Cell, + + /// The set of `ItemId`s that are allowlisted. This the very first thing + /// computed after parsing our IR, and before running any of our analyses. + allowlisted: Option, + + /// Cache for calls to `ParseCallbacks::blocklisted_type_implements_trait` + blocklisted_types_implement_traits: + RefCell>>, + + /// The set of `ItemId`s that are allowlisted for code generation _and_ that + /// we should generate accounting for the codegen options. + /// + /// It's computed right after computing the allowlisted items. + codegen_items: Option, + + /// Map from an item's ID to the set of template parameter items that it + /// uses. See `ir::named` for more details. Always `Some` during the codegen + /// phase. + used_template_parameters: Option>, + + /// The set of `TypeKind::Comp` items found during parsing that need their + /// bitfield allocation units computed. Drained in `compute_bitfield_units`. + need_bitfield_allocation: Vec, + + /// The set of enums that are defined by a pair of `enum` and `typedef`, + /// which is legal in C (but not C++). + /// + /// ```c++ + /// // in either order + /// enum Enum { Variants... }; + /// typedef int16_t Enum; + /// ``` + /// + /// The stored `ItemId` is that of the `TypeKind::Enum`, not of the + /// `TypeKind::Alias`. + /// + /// This is populated when we enter codegen by `compute_enum_typedef_combos` + /// and is always `None` before that and `Some` after. + enum_typedef_combos: Option>, + + /// The set of (`ItemId`s of) types that can't derive debug. + /// + /// This is populated when we enter codegen by `compute_cannot_derive_debug` + /// and is always `None` before that and `Some` after. + cannot_derive_debug: Option>, + + /// The set of (`ItemId`s of) types that can't derive default. + /// + /// This is populated when we enter codegen by `compute_cannot_derive_default` + /// and is always `None` before that and `Some` after. + cannot_derive_default: Option>, + + /// The set of (`ItemId`s of) types that can't derive copy. + /// + /// This is populated when we enter codegen by `compute_cannot_derive_copy` + /// and is always `None` before that and `Some` after. + cannot_derive_copy: Option>, + + /// The set of (`ItemId`s of) types that can't derive hash. + /// + /// This is populated when we enter codegen by `compute_can_derive_hash` + /// and is always `None` before that and `Some` after. + cannot_derive_hash: Option>, + + /// The map why specified `ItemId`s of) types that can't derive hash. + /// + /// This is populated when we enter codegen by + /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None` + /// before that and `Some` after. + cannot_derive_partialeq_or_partialord: Option>, + + /// The sizedness of types. + /// + /// This is populated by `compute_sizedness` and is always `None` before + /// that function is invoked and `Some` afterwards. + sizedness: Option>, + + /// The set of (`ItemId's of`) types that has vtable. + /// + /// Populated when we enter codegen by `compute_has_vtable`; always `None` + /// before that and `Some` after. + have_vtable: Option>, + + /// The set of (`ItemId's of`) types that has destructor. + /// + /// Populated when we enter codegen by `compute_has_destructor`; always `None` + /// before that and `Some` after. + have_destructor: Option>, + + /// The set of (`ItemId's of`) types that has array. + /// + /// Populated when we enter codegen by `compute_has_type_param_in_array`; always `None` + /// before that and `Some` after. + has_type_param_in_array: Option>, + + /// The set of (`ItemId's of`) types that has float. + /// + /// Populated when we enter codegen by `compute_has_float`; always `None` + /// before that and `Some` after. + has_float: Option>, +} + +/// A traversal of allowlisted items. +struct AllowlistedItemsTraversal<'ctx> { + ctx: &'ctx BindgenContext, + traversal: ItemTraversal<'ctx, ItemSet, Vec>, +} + +impl Iterator for AllowlistedItemsTraversal<'_> { + type Item = ItemId; + + fn next(&mut self) -> Option { + loop { + let id = self.traversal.next()?; + + if self.ctx.resolve_item(id).is_blocklisted(self.ctx) { + continue; + } + + return Some(id); + } + } +} + +impl<'ctx> AllowlistedItemsTraversal<'ctx> { + /// Construct a new allowlisted items traversal. + pub(crate) fn new( + ctx: &'ctx BindgenContext, + roots: R, + predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool, + ) -> Self + where + R: IntoIterator, + { + AllowlistedItemsTraversal { + ctx, + traversal: ItemTraversal::new(ctx, roots, predicate), + } + } +} + +impl BindgenContext { + /// Construct the context for the given `options`. + pub(crate) fn new( + options: BindgenOptions, + input_unsaved_files: &[clang::UnsavedFile], + ) -> Self { + // TODO(emilio): Use the CXTargetInfo here when available. + // + // see: https://reviews.llvm.org/D32389 + let index = clang::Index::new(false, true); + + let parse_options = + clang_sys::CXTranslationUnit_DetailedPreprocessingRecord; + + let translation_unit = { + let _t = + Timer::new("translation_unit").with_output(options.time_phases); + + clang::TranslationUnit::parse( + &index, + "", + &options.clang_args, + input_unsaved_files, + parse_options, + ).expect("libclang error; possible causes include: +- Invalid flag syntax +- Unrecognized flags +- Invalid flag arguments +- File I/O errors +- Host vs. target architecture mismatch +If you encounter an error missing from this list, please file an issue or a PR!") + }; + + let target_info = clang::TargetInfo::new(&translation_unit); + let root_module = Self::build_root_module(ItemId(0)); + let root_module_id = root_module.id().as_module_id_unchecked(); + + // depfiles need to include the explicitly listed headers too + let deps = options.input_headers.iter().cloned().collect(); + + BindgenContext { + items: vec![Some(root_module)], + includes: Default::default(), + deps, + types: Default::default(), + type_params: Default::default(), + modules: Default::default(), + root_module: root_module_id, + current_module: root_module_id, + semantic_parents: Default::default(), + currently_parsed_types: vec![], + parsed_macros: Default::default(), + replacements: Default::default(), + collected_typerefs: false, + in_codegen: false, + translation_unit, + fallback_tu: None, + target_info, + options, + generated_bindgen_complex: Cell::new(false), + generated_bindgen_float16: Cell::new(false), + generated_opaque_array: Default::default(), + allowlisted: None, + blocklisted_types_implement_traits: Default::default(), + codegen_items: None, + used_template_parameters: None, + need_bitfield_allocation: Default::default(), + enum_typedef_combos: None, + cannot_derive_debug: None, + cannot_derive_default: None, + cannot_derive_copy: None, + cannot_derive_hash: None, + cannot_derive_partialeq_or_partialord: None, + sizedness: None, + have_vtable: None, + have_destructor: None, + has_type_param_in_array: None, + has_float: None, + } + } + + /// Returns `true` if the target architecture is wasm32 + pub(crate) fn is_target_wasm32(&self) -> bool { + self.target_info.triple.starts_with("wasm32-") + } + + /// Creates a timer for the current bindgen phase. If `time_phases` is `true`, + /// the timer will print to stderr when it is dropped, otherwise it will do + /// nothing. + pub(crate) fn timer<'a>(&self, name: &'a str) -> Timer<'a> { + Timer::new(name).with_output(self.options.time_phases) + } + + /// Returns the pointer width to use for the target for the current + /// translation. + pub(crate) fn target_pointer_size(&self) -> usize { + self.target_info.pointer_width / 8 + } + + /// Returns the ABI, which is mostly useful for determining the mangling kind. + pub(crate) fn abi_kind(&self) -> ABIKind { + self.target_info.abi + } + + /// Get the stack of partially parsed types that we are in the middle of + /// parsing. + pub(crate) fn currently_parsed_types(&self) -> &[PartialType] { + &self.currently_parsed_types[..] + } + + /// Begin parsing the given partial type, and push it onto the + /// `currently_parsed_types` stack so that we won't infinite recurse if we + /// run into a reference to it while parsing it. + pub(crate) fn begin_parsing(&mut self, partial_ty: PartialType) { + self.currently_parsed_types.push(partial_ty); + } + + /// Finish parsing the current partial type, pop it off the + /// `currently_parsed_types` stack, and return it. + pub(crate) fn finish_parsing(&mut self) -> PartialType { + self.currently_parsed_types.pop().expect( + "should have been parsing a type, if we finished parsing a type", + ) + } + + /// Add the location of the `#include` directive for the `included_file`. + pub(crate) fn add_include( + &mut self, + source_file: String, + included_file: String, + offset: usize, + ) { + self.includes + .entry(included_file) + .or_insert((source_file, offset)); + } + + /// Get the location of the first `#include` directive for the `included_file`. + pub(crate) fn included_file_location( + &self, + included_file: &str, + ) -> Option<(String, usize)> { + self.includes.get(included_file).cloned() + } + + /// Add an included file. + pub(crate) fn add_dep(&mut self, dep: Box) { + self.deps.insert(dep); + } + + /// Get any included files. + pub(crate) fn deps(&self) -> &BTreeSet> { + &self.deps + } + + /// Define a new item. + /// + /// This inserts it into the internal items set, and its type into the + /// internal types set. + pub(crate) fn add_item( + &mut self, + item: Item, + declaration: Option, + location: Option, + ) { + debug!("BindgenContext::add_item({item:?}, declaration: {declaration:?}, loc: {location:?}"); + debug_assert!( + declaration.is_some() || + !item.kind().is_type() || + item.kind().expect_type().is_builtin_or_type_param() || + item.kind().expect_type().is_opaque(self, &item) || + item.kind().expect_type().is_unresolved_ref(), + "Adding a type without declaration?" + ); + + let id = item.id(); + let is_type = item.kind().is_type(); + let is_unnamed = is_type && item.expect_type().name().is_none(); + let is_template_instantiation = + is_type && item.expect_type().is_template_instantiation(); + + if item.id() != self.root_module { + self.add_item_to_module(&item); + } + + if is_type && item.expect_type().is_comp() { + self.need_bitfield_allocation.push(id); + } + + let old_item = self.items[id.0].replace(item); + assert!( + old_item.is_none(), + "should not have already associated an item with the given id" + ); + + // Unnamed items can have an USR, but they can't be referenced from + // other sites explicitly and the USR can match if the unnamed items are + // nested, so don't bother tracking them. + if !is_type || is_template_instantiation { + return; + } + if let Some(mut declaration) = declaration { + if !declaration.is_valid() { + if let Some(location) = location { + if location.is_template_like() { + declaration = location; + } + } + } + declaration = declaration.canonical(); + if !declaration.is_valid() { + // This could happen, for example, with types like `int*` or + // similar. + // + // Fortunately, we don't care about those types being + // duplicated, so we can just ignore them. + debug!( + "Invalid declaration {declaration:?} found for type {:?}", + self.resolve_item_fallible(id) + .unwrap() + .kind() + .expect_type() + ); + return; + } + + let key = if is_unnamed { + TypeKey::Declaration(declaration) + } else if let Some(usr) = declaration.usr() { + TypeKey::Usr(usr) + } else { + warn!("Valid declaration with no USR: {declaration:?}, {location:?}"); + TypeKey::Declaration(declaration) + }; + + let old = self.types.insert(key, id.as_type_id_unchecked()); + debug_assert_eq!(old, None); + } + } + + /// Ensure that every item (other than the root module) is in a module's + /// children list. This is to make sure that every allowlisted item get's + /// codegen'd, even if its parent is not allowlisted. See issue #769 for + /// details. + fn add_item_to_module(&mut self, item: &Item) { + assert_ne!(item.id(), self.root_module); + assert!(self.resolve_item_fallible(item.id()).is_none()); + + if let Some(ref mut parent) = self.items[item.parent_id().0] { + if let Some(module) = parent.as_module_mut() { + debug!( + "add_item_to_module: adding {:?} as child of parent module {:?}", + item.id(), + item.parent_id() + ); + + module.children_mut().insert(item.id()); + return; + } + } + + debug!( + "add_item_to_module: adding {:?} as child of current module {:?}", + item.id(), + self.current_module + ); + + self.items[self.current_module.0 .0] + .as_mut() + .expect("Should always have an item for self.current_module") + .as_module_mut() + .expect("self.current_module should always be a module") + .children_mut() + .insert(item.id()); + } + + /// Add a new named template type parameter to this context's item set. + pub(crate) fn add_type_param(&mut self, item: Item, definition: Cursor) { + debug!("BindgenContext::add_type_param: item = {item:?}; definition = {definition:?}"); + + assert!( + item.expect_type().is_type_param(), + "Should directly be a named type, not a resolved reference or anything" + ); + assert_eq!( + definition.kind(), + clang_sys::CXCursor_TemplateTypeParameter + ); + + self.add_item_to_module(&item); + + let id = item.id(); + let old_item = self.items[id.0].replace(item); + assert!( + old_item.is_none(), + "should not have already associated an item with the given id" + ); + + let old_named_ty = self + .type_params + .insert(definition, id.as_type_id_unchecked()); + assert!( + old_named_ty.is_none(), + "should not have already associated a named type with this id" + ); + } + + /// Get the named type defined at the given cursor location, if we've + /// already added one. + pub(crate) fn get_type_param(&self, definition: &Cursor) -> Option { + assert_eq!( + definition.kind(), + clang_sys::CXCursor_TemplateTypeParameter + ); + self.type_params.get(definition).copied() + } + + // TODO: Move all this syntax crap to other part of the code. + + /// Mangles a name so it doesn't conflict with any keyword. + #[rustfmt::skip] + pub(crate) fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> { + if name.contains('@') || + name.contains('?') || + name.contains('$') || + matches!( + name, + "abstract" | "alignof" | "as" | "async" | "await" | "become" | + "box" | "break" | "const" | "continue" | "crate" | "do" | + "dyn" | "else" | "enum" | "extern" | "false" | "final" | + "fn" | "for" | "gen" | "if" | "impl" | "in" | "let" | "loop" | + "macro" | "match" | "mod" | "move" | "mut" | "offsetof" | + "override" | "priv" | "proc" | "pub" | "pure" | "ref" | + "return" | "Self" | "self" | "sizeof" | "static" | + "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" | + "unsafe" | "unsized" | "use" | "virtual" | "where" | + "while" | "yield" | "str" | "bool" | "f32" | "f64" | + "usize" | "isize" | "u128" | "i128" | "u64" | "i64" | + "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_" + ) + { + let mut s = name.to_owned(); + s = s.replace('@', "_"); + s = s.replace('?', "_"); + s = s.replace('$', "_"); + s.push('_'); + return Cow::Owned(s); + } + Cow::Borrowed(name) + } + + /// Returns a mangled name as a rust identifier. + pub(crate) fn rust_ident(&self, name: S) -> Ident + where + S: AsRef, + { + self.rust_ident_raw(self.rust_mangle(name.as_ref())) + } + + /// Returns a mangled name as a rust identifier. + pub(crate) fn rust_ident_raw(&self, name: T) -> Ident + where + T: AsRef, + { + Ident::new(name.as_ref(), Span::call_site()) + } + + /// Iterate over all items that have been defined. + pub(crate) fn items(&self) -> impl Iterator { + self.items.iter().enumerate().filter_map(|(index, item)| { + let item = item.as_ref()?; + Some((ItemId(index), item)) + }) + } + + /// Have we collected all unresolved type references yet? + pub(crate) fn collected_typerefs(&self) -> bool { + self.collected_typerefs + } + + /// Gather all the unresolved type references. + fn collect_typerefs( + &mut self, + ) -> Vec<(ItemId, clang::Type, Cursor, Option)> { + debug_assert!(!self.collected_typerefs); + self.collected_typerefs = true; + let mut typerefs = vec![]; + + for (id, item) in self.items() { + let kind = item.kind(); + let Some(ty) = kind.as_type() else { continue }; + + if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) = + *ty.kind() + { + typerefs.push((id, *ty, loc, parent_id)); + } + } + typerefs + } + + /// Collect all of our unresolved type references and resolve them. + fn resolve_typerefs(&mut self) { + let _t = self.timer("resolve_typerefs"); + + let typerefs = self.collect_typerefs(); + + for (id, ty, loc, parent_id) in typerefs { + let _resolved = + { + let resolved = Item::from_ty(&ty, loc, parent_id, self) + .unwrap_or_else(|_| { + warn!("Could not resolve type reference, falling back \ + to opaque blob"); + Item::new_opaque_type(self.next_item_id(), &ty, self) + }); + + let item = self.items[id.0].as_mut().unwrap(); + *item.kind_mut().as_type_mut().unwrap().kind_mut() = + TypeKind::ResolvedTypeRef(resolved); + resolved + }; + + // Something in the STL is trolling me. I don't need this assertion + // right now, but worth investigating properly once this lands. + // + // debug_assert!(self.items.get(&resolved).is_some(), "How?"); + // + // if let Some(parent_id) = parent_id { + // assert_eq!(self.items[&resolved].parent_id(), parent_id); + // } + } + } + + /// Temporarily loan `Item` with the given `ItemId`. This provides means to + /// mutably borrow `Item` while having a reference to `BindgenContext`. + /// + /// `Item` with the given `ItemId` is removed from the context, given + /// closure is executed and then `Item` is placed back. + /// + /// # Panics + /// + /// Panics if attempt to resolve given `ItemId` inside the given + /// closure is made. + fn with_loaned_item(&mut self, id: ItemId, f: F) -> T + where + F: (FnOnce(&BindgenContext, &mut Item) -> T), + { + let mut item = self.items[id.0].take().unwrap(); + + let result = f(self, &mut item); + + let existing = self.items[id.0].replace(item); + assert!(existing.is_none()); + + result + } + + /// Compute the bitfield allocation units for all `TypeKind::Comp` items we + /// parsed. + fn compute_bitfield_units(&mut self) { + let _t = self.timer("compute_bitfield_units"); + + assert!(self.collected_typerefs()); + + let need_bitfield_allocation = + mem::take(&mut self.need_bitfield_allocation); + for id in need_bitfield_allocation { + self.with_loaned_item(id, |ctx, item| { + let ty = item.kind_mut().as_type_mut().unwrap(); + let layout = ty.layout(ctx); + ty.as_comp_mut() + .unwrap() + .compute_bitfield_units(ctx, layout.as_ref()); + }); + } + } + + /// Assign a new generated name for each anonymous field. + fn deanonymize_fields(&mut self) { + let _t = self.timer("deanonymize_fields"); + + let comp_item_ids: Vec = self + .items() + .filter_map(|(id, item)| { + if item.kind().as_type()?.is_comp() { + return Some(id); + } + None + }) + .collect(); + + for id in comp_item_ids { + self.with_loaned_item(id, |ctx, item| { + item.kind_mut() + .as_type_mut() + .unwrap() + .as_comp_mut() + .unwrap() + .deanonymize_fields(ctx); + }); + } + } + + /// Iterate over all items and replace any item that has been named in a + /// `replaces="SomeType"` annotation with the replacement type. + fn process_replacements(&mut self) { + let _t = self.timer("process_replacements"); + if self.replacements.is_empty() { + debug!("No replacements to process"); + return; + } + + // FIXME: This is linear, but the replaces="xxx" annotation was already + // there, and for better or worse it's useful, sigh... + // + // We leverage the ResolvedTypeRef thing, though, which is cool :P. + + let mut replacements = vec![]; + + for (id, item) in self.items() { + if item.annotations().use_instead_of().is_some() { + continue; + } + + // Calls to `canonical_name` are expensive, so eagerly filter out + // items that cannot be replaced. + let Some(ty) = item.kind().as_type() else { + continue; + }; + + match *ty.kind() { + TypeKind::Comp(..) | + TypeKind::TemplateAlias(..) | + TypeKind::Enum(..) | + TypeKind::Alias(..) => {} + _ => continue, + } + + let path = item.path_for_allowlisting(self); + let replacement = self.replacements.get(&path[1..]); + + if let Some(replacement) = replacement { + if *replacement != id { + // We set this just after parsing the annotation. It's + // very unlikely, but this can happen. + if self.resolve_item_fallible(*replacement).is_some() { + replacements.push(( + id.expect_type_id(self), + replacement.expect_type_id(self), + )); + } + } + } + } + + for (id, replacement_id) in replacements { + debug!("Replacing {id:?} with {replacement_id:?}"); + let new_parent = { + let item_id: ItemId = id.into(); + let item = self.items[item_id.0].as_mut().unwrap(); + *item.kind_mut().as_type_mut().unwrap().kind_mut() = + TypeKind::ResolvedTypeRef(replacement_id); + item.parent_id() + }; + + // Relocate the replacement item from where it was declared, to + // where the thing it is replacing was declared. + // + // First, we'll make sure that its parent ID is correct. + + let old_parent = self.resolve_item(replacement_id).parent_id(); + if new_parent == old_parent { + // Same parent and therefore also same containing + // module. Nothing to do here. + continue; + } + + let replacement_item_id: ItemId = replacement_id.into(); + self.items[replacement_item_id.0] + .as_mut() + .unwrap() + .set_parent_for_replacement(new_parent); + + // Second, make sure that it is in the correct module's children + // set. + + let old_module = { + let immut_self = &*self; + old_parent + .ancestors(immut_self) + .chain(Some(immut_self.root_module.into())) + .find(|id| { + let item = immut_self.resolve_item(*id); + item.as_module().is_some_and(|m| { + m.children().contains(&replacement_id.into()) + }) + }) + }; + let old_module = old_module + .expect("Every replacement item should be in a module"); + + let new_module = { + let immut_self = &*self; + new_parent + .ancestors(immut_self) + .find(|id| immut_self.resolve_item(*id).is_module()) + }; + let new_module = + new_module.unwrap_or_else(|| self.root_module.into()); + + if new_module == old_module { + // Already in the correct module. + continue; + } + + self.items[old_module.0] + .as_mut() + .unwrap() + .as_module_mut() + .unwrap() + .children_mut() + .remove(&replacement_id.into()); + + self.items[new_module.0] + .as_mut() + .unwrap() + .as_module_mut() + .unwrap() + .children_mut() + .insert(replacement_id.into()); + } + } + + /// Enter the code generation phase, invoke the given callback `cb`, and + /// leave the code generation phase. + pub(crate) fn gen( + mut self, + cb: F, + ) -> Result<(Out, BindgenOptions), CodegenError> + where + F: FnOnce(&Self) -> Result, + { + self.in_codegen = true; + + self.resolve_typerefs(); + self.compute_bitfield_units(); + self.process_replacements(); + + self.deanonymize_fields(); + + self.assert_no_dangling_references(); + + // Compute the allowlisted set after processing replacements and + // resolving type refs, as those are the final mutations of the IR + // graph, and their completion means that the IR graph is now frozen. + self.compute_allowlisted_and_codegen_items(); + + // Make sure to do this after processing replacements, since that messes + // with the parentage and module children, and we want to assert that it + // messes with them correctly. + self.assert_every_item_in_a_module(); + + self.compute_has_vtable(); + self.compute_sizedness(); + self.compute_has_destructor(); + self.find_used_template_parameters(); + self.compute_enum_typedef_combos(); + self.compute_cannot_derive_debug(); + self.compute_cannot_derive_default(); + self.compute_cannot_derive_copy(); + self.compute_has_type_param_in_array(); + self.compute_has_float(); + self.compute_cannot_derive_hash(); + self.compute_cannot_derive_partialord_partialeq_or_eq(); + + let ret = cb(&self)?; + Ok((ret, self.options)) + } + + /// When the `__testing_only_extra_assertions` feature is enabled, this + /// function walks the IR graph and asserts that we do not have any edges + /// referencing an `ItemId` for which we do not have an associated IR item. + fn assert_no_dangling_references(&self) { + if cfg!(feature = "__testing_only_extra_assertions") { + for _ in self.assert_no_dangling_item_traversal() { + // The iterator's next method does the asserting for us. + } + } + } + + fn assert_no_dangling_item_traversal( + &self, + ) -> traversal::AssertNoDanglingItemsTraversal<'_> { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + + let roots = self.items().map(|(id, _)| id); + traversal::AssertNoDanglingItemsTraversal::new( + self, + roots, + traversal::all_edges, + ) + } + + /// When the `__testing_only_extra_assertions` feature is enabled, walk over + /// every item and ensure that it is in the children set of one of its + /// module ancestors. + fn assert_every_item_in_a_module(&self) { + if cfg!(feature = "__testing_only_extra_assertions") { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + + for (id, _item) in self.items() { + if id == self.root_module { + continue; + } + + assert!( + { + let id = id + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(self) + .id(); + id.ancestors(self) + .chain(Some(self.root_module.into())) + .any(|ancestor| { + debug!("Checking if {id:?} is a child of {ancestor:?}"); + self.resolve_item(ancestor) + .as_module() + .is_some_and(|m| m.children().contains(&id)) + }) + }, + "{id:?} should be in some ancestor module's children set" + ); + } + } + } + + /// Compute for every type whether it is sized or not, and whether it is + /// sized or not as a base class. + fn compute_sizedness(&mut self) { + let _t = self.timer("compute_sizedness"); + assert!(self.sizedness.is_none()); + self.sizedness = Some(analyze::(self)); + } + + /// Look up whether the type with the given ID is sized or not. + pub(crate) fn lookup_sizedness(&self, id: TypeId) -> SizednessResult { + assert!( + self.in_codegen_phase(), + "We only compute sizedness after we've entered codegen" + ); + + self.sizedness + .as_ref() + .unwrap() + .get(&id) + .copied() + .unwrap_or(SizednessResult::ZeroSized) + } + + /// Compute whether the type has vtable. + fn compute_has_vtable(&mut self) { + let _t = self.timer("compute_has_vtable"); + assert!(self.have_vtable.is_none()); + self.have_vtable = Some(analyze::(self)); + } + + /// Look up whether the item with `id` has vtable or not. + pub(crate) fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult { + assert!( + self.in_codegen_phase(), + "We only compute vtables when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` has a + // vtable or not. + self.have_vtable + .as_ref() + .unwrap() + .get(&id.into()) + .copied() + .unwrap_or(HasVtableResult::No) + } + + /// Compute whether the type has a destructor. + fn compute_has_destructor(&mut self) { + let _t = self.timer("compute_has_destructor"); + assert!(self.have_destructor.is_none()); + self.have_destructor = Some(analyze::(self)); + } + + /// Look up whether the item with `id` has a destructor. + pub(crate) fn lookup_has_destructor(&self, id: TypeId) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute destructors when we enter codegen" + ); + + self.have_destructor.as_ref().unwrap().contains(&id.into()) + } + + fn find_used_template_parameters(&mut self) { + let _t = self.timer("find_used_template_parameters"); + if self.options.allowlist_recursively { + let used_params = analyze::(self); + self.used_template_parameters = Some(used_params); + } else { + // If you aren't recursively allowlisting, then we can't really make + // any sense of template parameter usage, and you're on your own. + let mut used_params = HashMap::default(); + for &id in self.allowlisted_items() { + used_params.entry(id).or_insert_with(|| { + id.self_template_params(self) + .into_iter() + .map(|p| p.into()) + .collect() + }); + } + self.used_template_parameters = Some(used_params); + } + } + + /// Return `true` if `item` uses the given `template_param`, `false` + /// otherwise. + /// + /// This method may only be called during the codegen phase, because the + /// template usage information is only computed as we enter the codegen + /// phase. + /// + /// If the item is blocklisted, then we say that it always uses the template + /// parameter. This is a little subtle. The template parameter usage + /// analysis only considers allowlisted items, and if any blocklisted item + /// shows up in the generated bindings, it is the user's responsibility to + /// manually provide a definition for them. To give them the most + /// flexibility when doing that, we assume that they use every template + /// parameter and always pass template arguments through in instantiations. + pub(crate) fn uses_template_parameter( + &self, + item: ItemId, + template_param: TypeId, + ) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute template parameter usage as we enter codegen" + ); + + if self.resolve_item(item).is_blocklisted(self) { + return true; + } + + let template_param = template_param + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(self) + .id(); + + self.used_template_parameters + .as_ref() + .expect("should have found template parameter usage if we're in codegen") + .get(&item).is_some_and(|items_used_params| items_used_params.contains(&template_param)) + } + + /// Return `true` if `item` uses any unbound, generic template parameters, + /// `false` otherwise. + /// + /// Has the same restrictions that `uses_template_parameter` has. + pub(crate) fn uses_any_template_parameters(&self, item: ItemId) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute template parameter usage as we enter codegen" + ); + + self.used_template_parameters + .as_ref() + .expect( + "should have template parameter usage info in codegen phase", + ) + .get(&item) + .is_some_and(|used| !used.is_empty()) + } + + // This deserves a comment. Builtin types don't get a valid declaration, so + // we can't add it to the cursor->type map. + // + // That being said, they're not generated anyway, and are few, so the + // duplication and special-casing is fine. + // + // If at some point we care about the memory here, probably a map TypeKind + // -> builtin type ItemId would be the best to improve that. + fn add_builtin_item(&mut self, item: Item) { + debug!("add_builtin_item: item = {item:?}"); + debug_assert!(item.kind().is_type()); + self.add_item_to_module(&item); + let id = item.id(); + let old_item = self.items[id.0].replace(item); + assert!(old_item.is_none(), "Inserted type twice?"); + } + + fn build_root_module(id: ItemId) -> Item { + let module = Module::new(Some("root".into()), ModuleKind::Normal); + Item::new(id, None, None, id, ItemKind::Module(module), None) + } + + /// Get the root module. + pub(crate) fn root_module(&self) -> ModuleId { + self.root_module + } + + /// Resolve a type with the given ID. + /// + /// Panics if there is no item for the given `TypeId` or if the resolved + /// item is not a `Type`. + pub(crate) fn resolve_type(&self, type_id: TypeId) -> &Type { + self.resolve_item(type_id).kind().expect_type() + } + + /// Resolve a function with the given ID. + /// + /// Panics if there is no item for the given `FunctionId` or if the resolved + /// item is not a `Function`. + pub(crate) fn resolve_func(&self, func_id: FunctionId) -> &Function { + self.resolve_item(func_id).kind().expect_function() + } + + /// Resolve the given `ItemId` as a type, or `None` if there is no item with + /// the given ID. + /// + /// Panics if the ID resolves to an item that is not a type. + pub(crate) fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> { + self.resolve_item_fallible(type_id) + .map(|t| t.kind().expect_type()) + } + + /// Resolve the given `ItemId` into an `Item`, or `None` if no such item + /// exists. + pub(crate) fn resolve_item_fallible>( + &self, + id: Id, + ) -> Option<&Item> { + self.items.get(id.into().0)?.as_ref() + } + + /// Resolve the given `ItemId` into an `Item`. + /// + /// Panics if the given ID does not resolve to any item. + pub(crate) fn resolve_item>(&self, item_id: Id) -> &Item { + let item_id = item_id.into(); + match self.resolve_item_fallible(item_id) { + Some(item) => item, + None => panic!("Not an item: {item_id:?}"), + } + } + + /// Get the current module. + pub(crate) fn current_module(&self) -> ModuleId { + self.current_module + } + + /// Add a semantic parent for a given type definition. + /// + /// We do this from the type declaration, in order to be able to find the + /// correct type definition afterwards. + /// + /// TODO(emilio): We could consider doing this only when + /// `declaration.lexical_parent() != definition.lexical_parent()`, but it's + /// not sure it's worth it. + pub(crate) fn add_semantic_parent( + &mut self, + definition: Cursor, + parent_id: ItemId, + ) { + self.semantic_parents.insert(definition, parent_id); + } + + /// Returns a known semantic parent for a given definition. + pub(crate) fn known_semantic_parent( + &self, + definition: Cursor, + ) -> Option { + self.semantic_parents.get(&definition).copied() + } + + /// Given a cursor pointing to the location of a template instantiation, + /// return a tuple of the form `(declaration_cursor, declaration_id, + /// num_expected_template_args)`. + /// + /// Note that `declaration_id` is not guaranteed to be in the context's item + /// set! It is possible that it is a partial type that we are still in the + /// middle of parsing. + fn get_declaration_info_for_template_instantiation( + &self, + instantiation: &Cursor, + ) -> Option<(Cursor, ItemId, usize)> { + instantiation + .cur_type() + .canonical_declaration(Some(instantiation)) + .and_then(|canon_decl| { + self.get_resolved_type(&canon_decl).and_then( + |template_decl_id| { + let num_params = + template_decl_id.num_self_template_params(self); + if num_params == 0 { + None + } else { + Some(( + *canon_decl.cursor(), + template_decl_id.into(), + num_params, + )) + } + }, + ) + }) + .or_else(|| { + // If we haven't already parsed the declaration of + // the template being instantiated, then it *must* + // be on the stack of types we are currently + // parsing. If it wasn't then clang would have + // already errored out before we started + // constructing our IR because you can't instantiate + // a template until it is fully defined. + instantiation + .referenced() + .and_then(|referenced| { + self.currently_parsed_types() + .iter() + .find(|partial_ty| *partial_ty.decl() == referenced) + }) + .and_then(|template_decl| { + let num_template_params = + template_decl.num_self_template_params(self); + if num_template_params == 0 { + None + } else { + Some(( + *template_decl.decl(), + template_decl.id(), + num_template_params, + )) + } + }) + }) + } + + /// Parse a template instantiation, eg `Foo`. + /// + /// This is surprisingly difficult to do with libclang, due to the fact that + /// it doesn't provide explicit template argument information, except for + /// function template declarations(!?!??!). + /// + /// The only way to do this is manually inspecting the AST and looking for + /// `TypeRefs` and `TemplateRefs` inside. This, unfortunately, doesn't work for + /// more complex cases, see the comment on the assertion below. + /// + /// To add insult to injury, the AST itself has structure that doesn't make + /// sense. Sometimes `Foo>` has an AST with nesting like you might + /// expect: `(Foo (Bar (int)))`. Other times, the AST we get is completely + /// flat: `(Foo Bar int)`. + /// + /// To see an example of what this method handles: + /// + /// ```c++ + /// template + /// class Incomplete { + /// T p; + /// }; + /// + /// template + /// class Foo { + /// Incomplete bar; + /// }; + /// ``` + /// + /// Finally, template instantiations are always children of the current + /// module. They use their template's definition for their name, so the + /// parent is only useful for ensuring that their layout tests get + /// codegen'd. + fn instantiate_template( + &mut self, + with_id: ItemId, + template: TypeId, + ty: &clang::Type, + location: Cursor, + ) -> Option { + let num_expected_args = + self.resolve_type(template).num_self_template_params(self); + if num_expected_args == 0 { + warn!( + "Tried to instantiate a template for which we could not \ + determine any template parameters" + ); + return None; + } + + let mut args = vec![]; + let mut found_const_arg = false; + let mut children = location.collect_children(); + + if children.iter().all(|c| !c.has_children()) { + // This is insanity... If clang isn't giving us a properly nested + // AST for which template arguments belong to which template we are + // instantiating, we'll need to construct it ourselves. However, + // there is an extra `NamespaceRef, NamespaceRef, ..., TemplateRef` + // representing a reference to the outermost template declaration + // that we need to filter out of the children. We need to do this + // filtering because we already know which template declaration is + // being specialized via the `location`'s type, and if we do not + // filter it out, we'll add an extra layer of template instantiation + // on accident. + let idx = children + .iter() + .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef); + if let Some(idx) = idx { + if children + .iter() + .take(idx) + .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef) + { + children = children.into_iter().skip(idx + 1).collect(); + } + } + } + + for child in children.iter().rev() { + match child.kind() { + clang_sys::CXCursor_TypeRef | + clang_sys::CXCursor_TypedefDecl | + clang_sys::CXCursor_TypeAliasDecl => { + // The `with_id` ID will potentially end up unused if we give up + // on this type (for example, because it has const value + // template args), so if we pass `with_id` as the parent, it is + // potentially a dangling reference. Instead, use the canonical + // template declaration as the parent. It is already parsed and + // has a known-resolvable `ItemId`. + let ty = Item::from_ty_or_ref( + child.cur_type(), + *child, + Some(template.into()), + self, + ); + args.push(ty); + } + clang_sys::CXCursor_TemplateRef => { + let ( + template_decl_cursor, + template_decl_id, + num_expected_template_args, + ) = self.get_declaration_info_for_template_instantiation( + child, + )?; + + if num_expected_template_args == 0 || + child.has_at_least_num_children( + num_expected_template_args, + ) + { + // Do a happy little parse. See comment in the TypeRef + // match arm about parent IDs. + let ty = Item::from_ty_or_ref( + child.cur_type(), + *child, + Some(template.into()), + self, + ); + args.push(ty); + } else { + // This is the case mentioned in the doc comment where + // clang gives us a flattened AST and we have to + // reconstruct which template arguments go to which + // instantiation :( + let args_len = args.len(); + if args_len < num_expected_template_args { + warn!( + "Found a template instantiation without \ + enough template arguments" + ); + return None; + } + + let mut sub_args: Vec<_> = args + .drain(args_len - num_expected_template_args..) + .collect(); + sub_args.reverse(); + + let sub_name = Some(template_decl_cursor.spelling()); + let sub_inst = TemplateInstantiation::new( + // This isn't guaranteed to be a type that we've + // already finished parsing yet. + template_decl_id.as_type_id_unchecked(), + sub_args, + ); + let sub_kind = + TypeKind::TemplateInstantiation(sub_inst); + let sub_ty = Type::new( + sub_name, + template_decl_cursor + .cur_type() + .fallible_layout(self) + .ok(), + sub_kind, + false, + ); + let sub_id = self.next_item_id(); + let sub_item = Item::new( + sub_id, + None, + None, + self.current_module.into(), + ItemKind::Type(sub_ty), + Some(child.location()), + ); + + // Bypass all the validations in add_item explicitly. + debug!( + "instantiate_template: inserting nested \ + instantiation item: {sub_item:?}" + ); + self.add_item_to_module(&sub_item); + debug_assert_eq!(sub_id, sub_item.id()); + self.items[sub_id.0] = Some(sub_item); + args.push(sub_id.as_type_id_unchecked()); + } + } + _ => { + warn!( + "Found template arg cursor we can't handle: {child:?}" + ); + found_const_arg = true; + } + } + } + + if found_const_arg { + // This is a dependently typed template instantiation. That is, an + // instantiation of a template with one or more const values as + // template arguments, rather than only types as template + // arguments. For example, `Foo` versus `Bar`. + // We can't handle these instantiations, so just punt in this + // situation... + warn!( + "Found template instantiated with a const value; \ + bindgen can't handle this kind of template instantiation!" + ); + return None; + } + + if args.len() != num_expected_args { + warn!( + "Found a template with an unexpected number of template \ + arguments" + ); + return None; + } + + args.reverse(); + let type_kind = TypeKind::TemplateInstantiation( + TemplateInstantiation::new(template, args), + ); + let name = ty.spelling(); + let name = if name.is_empty() { None } else { Some(name) }; + let ty = Type::new( + name, + ty.fallible_layout(self).ok(), + type_kind, + ty.is_const(), + ); + let item = Item::new( + with_id, + None, + None, + self.current_module.into(), + ItemKind::Type(ty), + Some(location.location()), + ); + + // Bypass all the validations in add_item explicitly. + debug!("instantiate_template: inserting item: {item:?}"); + self.add_item_to_module(&item); + debug_assert_eq!(with_id, item.id()); + self.items[with_id.0] = Some(item); + Some(with_id.as_type_id_unchecked()) + } + + /// If we have already resolved the type for the given type declaration, + /// return its `ItemId`. Otherwise, return `None`. + pub(crate) fn get_resolved_type( + &self, + decl: &clang::CanonicalTypeDeclaration, + ) -> Option { + self.types + .get(&TypeKey::Declaration(*decl.cursor())) + .or_else(|| { + decl.cursor() + .usr() + .and_then(|usr| self.types.get(&TypeKey::Usr(usr))) + }) + .copied() + } + + /// Looks up for an already resolved type, either because it's builtin, or + /// because we already have it in the map. + pub(crate) fn builtin_or_resolved_ty( + &mut self, + with_id: ItemId, + parent_id: Option, + ty: &clang::Type, + location: Option, + ) -> Option { + use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef}; + debug!("builtin_or_resolved_ty: {ty:?}, {location:?}, {with_id:?}, {parent_id:?}"); + + if let Some(decl) = ty.canonical_declaration(location.as_ref()) { + if let Some(id) = self.get_resolved_type(&decl) { + debug!( + "Already resolved ty {id:?}, {decl:?}, {ty:?} {location:?}" + ); + // If the declaration already exists, then either: + // + // * the declaration is a template declaration of some sort, + // and we are looking at an instantiation or specialization + // of it, or + // * we have already parsed and resolved this type, and + // there's nothing left to do. + if let Some(location) = location { + if decl.cursor().is_template_like() && + *ty != decl.cursor().cur_type() + { + // For specialized type aliases, there's no way to get the + // template parameters as of this writing (for a struct + // specialization we wouldn't be in this branch anyway). + // + // Explicitly return `None` if there aren't any + // unspecialized parameters (contains any `TypeRef`) so we + // resolve the canonical type if there is one and it's + // exposed. + // + // This is _tricky_, I know :( + if decl.cursor().kind() == + CXCursor_TypeAliasTemplateDecl && + !location.contains_cursor(CXCursor_TypeRef) && + ty.canonical_type().is_valid_and_exposed() + { + return None; + } + + return self + .instantiate_template(with_id, id, ty, location) + .or(Some(id)); + } + } + + return Some(self.build_ty_wrapper(with_id, id, parent_id, ty)); + } + } + + debug!("Not resolved, maybe builtin?"); + self.build_builtin_ty(ty) + } + + /// Make a new item that is a resolved type reference to the `wrapped_id`. + /// + /// This is unfortunately a lot of bloat, but is needed to properly track + /// constness et al. + /// + /// We should probably make the constness tracking separate, so it doesn't + /// bloat that much, but hey, we already bloat the heck out of builtin + /// types. + pub(crate) fn build_ty_wrapper( + &mut self, + with_id: ItemId, + wrapped_id: TypeId, + parent_id: Option, + ty: &clang::Type, + ) -> TypeId { + self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const()) + } + + /// A wrapper over a type that adds a const qualifier explicitly. + /// + /// Needed to handle const methods in C++, wrapping the type . + pub(crate) fn build_const_wrapper( + &mut self, + with_id: ItemId, + wrapped_id: TypeId, + parent_id: Option, + ty: &clang::Type, + ) -> TypeId { + self.build_wrapper( + with_id, wrapped_id, parent_id, ty, /* is_const = */ true, + ) + } + + fn build_wrapper( + &mut self, + with_id: ItemId, + wrapped_id: TypeId, + parent_id: Option, + ty: &clang::Type, + is_const: bool, + ) -> TypeId { + let spelling = ty.spelling(); + let layout = ty.fallible_layout(self).ok(); + let location = ty.declaration().location(); + let type_kind = TypeKind::ResolvedTypeRef(wrapped_id); + let ty = Type::new(Some(spelling), layout, type_kind, is_const); + let item = Item::new( + with_id, + None, + None, + parent_id.unwrap_or_else(|| self.current_module.into()), + ItemKind::Type(ty), + Some(location), + ); + self.add_builtin_item(item); + with_id.as_type_id_unchecked() + } + + /// Returns the next item ID to be used for an item. + pub(crate) fn next_item_id(&mut self) -> ItemId { + let ret = ItemId(self.items.len()); + self.items.push(None); + ret + } + + fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option { + use clang_sys::*; + let type_kind = match ty.kind() { + CXType_NullPtr => TypeKind::NullPtr, + CXType_Void => TypeKind::Void, + CXType_Bool => TypeKind::Int(IntKind::Bool), + CXType_Int => TypeKind::Int(IntKind::Int), + CXType_UInt => TypeKind::Int(IntKind::UInt), + CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }), + CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }), + CXType_SChar => TypeKind::Int(IntKind::SChar), + CXType_UChar => TypeKind::Int(IntKind::UChar), + CXType_Short => TypeKind::Int(IntKind::Short), + CXType_UShort => TypeKind::Int(IntKind::UShort), + CXType_WChar => TypeKind::Int(IntKind::WChar), + CXType_Char16 if self.options().use_distinct_char16_t => { + TypeKind::Int(IntKind::Char16) + } + CXType_Char16 => TypeKind::Int(IntKind::U16), + CXType_Char32 => TypeKind::Int(IntKind::U32), + CXType_Long => TypeKind::Int(IntKind::Long), + CXType_ULong => TypeKind::Int(IntKind::ULong), + CXType_LongLong => TypeKind::Int(IntKind::LongLong), + CXType_ULongLong => TypeKind::Int(IntKind::ULongLong), + CXType_Int128 => TypeKind::Int(IntKind::I128), + CXType_UInt128 => TypeKind::Int(IntKind::U128), + CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16), + CXType_Float => TypeKind::Float(FloatKind::Float), + CXType_Double => TypeKind::Float(FloatKind::Double), + CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble), + CXType_Float128 => TypeKind::Float(FloatKind::Float128), + CXType_Complex => { + let float_type = + ty.elem_type().expect("Not able to resolve complex type?"); + let float_kind = match float_type.kind() { + CXType_Float16 | CXType_Half => FloatKind::Float16, + CXType_Float => FloatKind::Float, + CXType_Double => FloatKind::Double, + CXType_LongDouble => FloatKind::LongDouble, + CXType_Float128 => FloatKind::Float128, + _ => panic!( + "Non floating-type complex? {ty:?}, {float_type:?}", + ), + }; + TypeKind::Complex(float_kind) + } + _ => return None, + }; + + let spelling = ty.spelling(); + let is_const = ty.is_const(); + let layout = ty.fallible_layout(self).ok(); + let location = ty.declaration().location(); + let ty = Type::new(Some(spelling), layout, type_kind, is_const); + let id = self.next_item_id(); + let item = Item::new( + id, + None, + None, + self.root_module.into(), + ItemKind::Type(ty), + Some(location), + ); + self.add_builtin_item(item); + Some(id.as_type_id_unchecked()) + } + + /// Get the current Clang translation unit that is being processed. + pub(crate) fn translation_unit(&self) -> &clang::TranslationUnit { + &self.translation_unit + } + + /// Initialize fallback translation unit if it does not exist and + /// then return a mutable reference to the fallback translation unit. + pub(crate) fn try_ensure_fallback_translation_unit( + &mut self, + ) -> Option<&mut clang::FallbackTranslationUnit> { + if self.fallback_tu.is_none() { + let file = format!( + "{}/.macro_eval.c", + match self.options().clang_macro_fallback_build_dir { + Some(ref path) => path.as_os_str().to_str()?, + None => ".", + } + ); + + let index = clang::Index::new(false, false); + + let mut header_names_to_compile = Vec::new(); + let mut header_paths = Vec::new(); + let mut header_includes = Vec::new(); + let single_header = self.options().input_headers.last().cloned()?; + for input_header in &self.options.input_headers + [..self.options.input_headers.len() - 1] + { + let path = Path::new(input_header.as_ref()); + if let Some(header_path) = path.parent() { + if header_path == Path::new("") { + header_paths.push("."); + } else { + header_paths.push(header_path.as_os_str().to_str()?); + } + } else { + header_paths.push("."); + } + let header_name = path.file_name()?.to_str()?; + header_includes.push(header_name.to_string()); + header_names_to_compile + .push(header_name.split(".h").next()?.to_string()); + } + let pch = format!( + "{}/{}", + match self.options().clang_macro_fallback_build_dir { + Some(ref path) => path.as_os_str().to_str()?, + None => ".", + }, + header_names_to_compile.join("-") + "-precompile.h.pch" + ); + + let mut c_args = self.options.fallback_clang_args.clone(); + c_args.push("-x".to_string().into_boxed_str()); + c_args.push("c-header".to_string().into_boxed_str()); + for header_path in header_paths { + c_args.push(format!("-I{header_path}").into_boxed_str()); + } + for header_include in header_includes { + c_args.push("-include".to_string().into_boxed_str()); + c_args.push(header_include.into_boxed_str()); + } + let mut tu = clang::TranslationUnit::parse( + &index, + &single_header, + &c_args, + &[], + clang_sys::CXTranslationUnit_ForSerialization, + )?; + tu.save(&pch).ok()?; + + let mut c_args = vec![ + "-include-pch".to_string().into_boxed_str(), + pch.clone().into_boxed_str(), + ]; + let mut skip_next = false; + for arg in &self.options.fallback_clang_args { + if arg.as_ref() == "-include" { + skip_next = true; + } else if skip_next { + skip_next = false; + } else { + c_args.push(arg.clone()); + } + } + self.fallback_tu = + Some(clang::FallbackTranslationUnit::new(file, pch, &c_args)?); + } + + self.fallback_tu.as_mut() + } + + /// Have we parsed the macro named `macro_name` already? + pub(crate) fn parsed_macro(&self, macro_name: &[u8]) -> bool { + self.parsed_macros.contains_key(macro_name) + } + + /// Get the currently parsed macros. + pub(crate) fn parsed_macros( + &self, + ) -> &StdHashMap, cexpr::expr::EvalResult> { + debug_assert!(!self.in_codegen_phase()); + &self.parsed_macros + } + + /// Mark the macro named `macro_name` as parsed. + pub(crate) fn note_parsed_macro( + &mut self, + id: Vec, + value: cexpr::expr::EvalResult, + ) { + self.parsed_macros.insert(id, value); + } + + /// Are we in the codegen phase? + pub(crate) fn in_codegen_phase(&self) -> bool { + self.in_codegen + } + + /// Mark the type with the given `name` as replaced by the type with ID + /// `potential_ty`. + /// + /// Replacement types are declared using the `replaces="xxx"` annotation, + /// and implies that the original type is hidden. + pub(crate) fn replace(&mut self, name: &[String], potential_ty: ItemId) { + match self.replacements.entry(name.into()) { + Entry::Vacant(entry) => { + debug!("Defining replacement for {name:?} as {potential_ty:?}"); + entry.insert(potential_ty); + } + Entry::Occupied(occupied) => { + warn!( + "Replacement for {name:?} already defined as {:?}; \ + ignoring duplicate replacement definition as {potential_ty:?}", + occupied.get(), + ); + } + } + } + + /// Has the item with the given `name` and `id` been replaced by another + /// type? + pub(crate) fn is_replaced_type>( + &self, + path: &[String], + id: Id, + ) -> bool { + let id = id.into(); + matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id) + } + + /// Is the type with the given `name` marked as opaque? + pub(crate) fn opaque_by_name(&self, path: &[String]) -> bool { + debug_assert!( + self.in_codegen_phase(), + "You're not supposed to call this yet" + ); + self.options.opaque_types.matches(path[1..].join("::")) + } + + /// Get the options used to configure this bindgen context. + pub(crate) fn options(&self) -> &BindgenOptions { + &self.options + } + + /// Tokenizes a namespace cursor in order to get the name and kind of the + /// namespace. + fn tokenize_namespace( + &self, + cursor: &Cursor, + ) -> (Option, ModuleKind) { + assert_eq!( + cursor.kind(), + ::clang_sys::CXCursor_Namespace, + "Be a nice person" + ); + + let mut module_name = None; + let spelling = cursor.spelling(); + if !spelling.is_empty() { + module_name = Some(spelling); + } + + let mut kind = ModuleKind::Normal; + let mut looking_for_name = false; + for token in cursor.tokens().iter() { + match token.spelling() { + b"inline" => { + debug_assert!( + kind != ModuleKind::Inline, + "Multiple inline keywords?" + ); + kind = ModuleKind::Inline; + // When hitting a nested inline namespace we get a spelling + // that looks like ["inline", "foo"]. Deal with it properly. + looking_for_name = true; + } + // The double colon allows us to handle nested namespaces like + // namespace foo::bar { } + // + // libclang still gives us two namespace cursors, which is cool, + // but the tokenization of the second begins with the double + // colon. That's ok, so we only need to handle the weird + // tokenization here. + b"namespace" | b"::" => { + looking_for_name = true; + } + b"{" => { + // This should be an anonymous namespace. + assert!(looking_for_name); + break; + } + name => { + if looking_for_name { + if module_name.is_none() { + module_name = Some( + String::from_utf8_lossy(name).into_owned(), + ); + } + break; + } + // This is _likely_, but not certainly, a macro that's + // been placed just before the namespace keyword. + // Unfortunately, clang tokens don't let us easily see + // through the ifdef tokens, so we don't know what this + // token should really be. Instead of panicking though, + // we warn the user that we assumed the token was blank, + // and then move on. + // + // See also https://github.com/rust-lang/rust-bindgen/issues/1676. + warn!("Ignored unknown namespace prefix '{}' at {token:?} in {cursor:?}", String::from_utf8_lossy(name)); + } + } + } + + if cursor.is_inline_namespace() { + kind = ModuleKind::Inline; + } + + (module_name, kind) + } + + /// Given a `CXCursor_Namespace` cursor, return the item ID of the + /// corresponding module, or create one on the fly. + pub(crate) fn module(&mut self, cursor: Cursor) -> ModuleId { + use clang_sys::*; + assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person"); + let cursor = cursor.canonical(); + if let Some(id) = self.modules.get(&cursor) { + return *id; + } + + let (module_name, kind) = self.tokenize_namespace(&cursor); + + let module_id = self.next_item_id(); + let module = Module::new(module_name, kind); + let module = Item::new( + module_id, + None, + None, + self.current_module.into(), + ItemKind::Module(module), + Some(cursor.location()), + ); + + let module_id = module.id().as_module_id_unchecked(); + self.modules.insert(cursor, module_id); + + self.add_item(module, None, None); + + module_id + } + + /// Start traversing the module with the given `module_id`, invoke the + /// callback `cb`, and then return to traversing the original module. + pub(crate) fn with_module(&mut self, module_id: ModuleId, cb: F) + where + F: FnOnce(&mut Self), + { + debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat"); + + let previous_id = self.current_module; + self.current_module = module_id; + + cb(self); + + self.current_module = previous_id; + } + + /// Iterate over all (explicitly or transitively) allowlisted items. + /// + /// If no items are explicitly allowlisted, then all items are considered + /// allowlisted. + pub(crate) fn allowlisted_items(&self) -> &ItemSet { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + + self.allowlisted.as_ref().unwrap() + } + + /// Check whether a particular blocklisted type implements a trait or not. + /// Results may be cached. + pub(crate) fn blocklisted_type_implements_trait( + &self, + item: &Item, + derive_trait: DeriveTrait, + ) -> CanDerive { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + + *self + .blocklisted_types_implement_traits + .borrow_mut() + .entry(derive_trait) + .or_default() + .entry(item.id()) + .or_insert_with(|| { + item.expect_type() + .name() + .and_then(|name| { + if self.options.parse_callbacks.is_empty() { + // Sized integer types from get mapped to Rust primitive + // types regardless of whether they are blocklisted, so ensure that + // standard traits are considered derivable for them too. + if self.is_stdint_type(name) { + Some(CanDerive::Yes) + } else { + Some(CanDerive::No) + } + } else { + self.options.last_callback(|cb| { + cb.blocklisted_type_implements_trait( + name, + derive_trait, + ) + }) + } + }) + .unwrap_or(CanDerive::No) + }) + } + + /// Is the given type a type from that corresponds to a Rust primitive type? + pub(crate) fn is_stdint_type(&self, name: &str) -> bool { + match name { + "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" | + "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" | + "intptr_t" | "ptrdiff_t" => true, + "size_t" | "ssize_t" => self.options.size_t_is_usize, + _ => false, + } + } + + /// Get a reference to the set of items we should generate. + pub(crate) fn codegen_items(&self) -> &ItemSet { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + self.codegen_items.as_ref().unwrap() + } + + /// Compute the allowlisted items set and populate `self.allowlisted`. + fn compute_allowlisted_and_codegen_items(&mut self) { + assert!(self.in_codegen_phase()); + assert_eq!(self.current_module, self.root_module); + assert!(self.allowlisted.is_none()); + let _t = self.timer("compute_allowlisted_and_codegen_items"); + + let roots = { + let mut roots = self + .items() + // Only consider roots that are enabled for codegen. + .filter(|&(_, item)| item.is_enabled_for_codegen(self)) + .filter(|&(_, item)| { + // If nothing is explicitly allowlisted, then everything is fair + // game. + if self.options().allowlisted_types.is_empty() && + self.options().allowlisted_functions.is_empty() && + self.options().allowlisted_vars.is_empty() && + self.options().allowlisted_files.is_empty() && + self.options().allowlisted_items.is_empty() + { + return true; + } + + // If this is a type that explicitly replaces another, we assume + // you know what you're doing. + if item.annotations().use_instead_of().is_some() { + return true; + } + + // Items with a source location in an explicitly allowlisted file + // are always included. + if !self.options().allowlisted_files.is_empty() { + if let Some(location) = item.location() { + let (file, _, _, _) = location.location(); + if let Some(filename) = file.name() { + if self + .options() + .allowlisted_files + .matches(filename) + { + return true; + } + } + } + } + + let name = item.path_for_allowlisting(self)[1..].join("::"); + debug!("allowlisted_items: testing {name:?}"); + + if self.options().allowlisted_items.matches(&name) { + return true; + } + + match *item.kind() { + ItemKind::Module(..) => true, + ItemKind::Function(_) => { + self.options().allowlisted_functions.matches(&name) + } + ItemKind::Var(_) => { + self.options().allowlisted_vars.matches(&name) + } + ItemKind::Type(ref ty) => { + if self.options().allowlisted_types.matches(&name) { + return true; + } + + // Auto-allowlist types that don't need code + // generation if not allowlisting recursively, to + // make the #[derive] analysis not be lame. + if !self.options().allowlist_recursively { + match *ty.kind() { + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Array(..) | + TypeKind::Vector(..) | + TypeKind::Pointer(..) | + TypeKind::Reference(..) | + TypeKind::Function(..) | + TypeKind::ResolvedTypeRef(..) | + TypeKind::Opaque | + TypeKind::TypeParam => return true, + _ => {} + } + if self.is_stdint_type(&name) { + return true; + } + } + + // Unnamed top-level enums are special and we + // allowlist them via the `allowlisted_vars` filter, + // since they're effectively top-level constants, + // and there's no way for them to be referenced + // consistently. + let parent = self.resolve_item(item.parent_id()); + if !parent.is_module() { + return false; + } + + let TypeKind::Enum(ref enum_) = *ty.kind() else { + return false; + }; + + if ty.name().is_some() { + return false; + } + + let mut prefix_path = + parent.path_for_allowlisting(self).clone(); + enum_.variants().iter().any(|variant| { + prefix_path.push( + variant.name_for_allowlisting().into(), + ); + let name = prefix_path[1..].join("::"); + prefix_path.pop().unwrap(); + self.options().allowlisted_vars.matches(&name) + || self + .options() + .allowlisted_items + .matches(name) + }) + } + } + }) + .map(|(id, _)| id) + .collect::>(); + + // The reversal preserves the expected ordering of traversal, + // resulting in more stable-ish bindgen-generated names for + // anonymous types (like unions). + roots.reverse(); + roots + }; + + let allowlisted_items_predicate = + if self.options().allowlist_recursively { + traversal::all_edges + } else { + // Only follow InnerType edges from the allowlisted roots. + // Such inner types (e.g. anonymous structs/unions) are + // always emitted by codegen, and they need to be allowlisted + // to make sure they are processed by e.g. the derive analysis. + traversal::only_inner_type_edges + }; + + let allowlisted = AllowlistedItemsTraversal::new( + self, + roots.clone(), + allowlisted_items_predicate, + ) + .collect::(); + + let codegen_items = if self.options().allowlist_recursively { + AllowlistedItemsTraversal::new( + self, + roots, + traversal::codegen_edges, + ) + .collect::() + } else { + allowlisted.clone() + }; + + self.allowlisted = Some(allowlisted); + self.codegen_items = Some(codegen_items); + + for item in self.options().allowlisted_functions.unmatched_items() { + unused_regex_diagnostic(item, "--allowlist-function", self); + } + + for item in self.options().allowlisted_vars.unmatched_items() { + unused_regex_diagnostic(item, "--allowlist-var", self); + } + + for item in self.options().allowlisted_types.unmatched_items() { + unused_regex_diagnostic(item, "--allowlist-type", self); + } + + for item in self.options().allowlisted_items.unmatched_items() { + unused_regex_diagnostic(item, "--allowlist-items", self); + } + } + + /// Convenient method for getting the prefix to use for most traits in + /// codegen depending on the `use_core` option. + pub(crate) fn trait_prefix(&self) -> Ident { + if self.options().use_core { + self.rust_ident_raw("core") + } else { + self.rust_ident_raw("std") + } + } + + /// Call if an opaque array is generated + pub(crate) fn generated_opaque_array(&self, align: usize) { + self.generated_opaque_array.borrow_mut().insert(align); + } + + /// Whether we need to generate the opaque array type + pub(crate) fn opaque_array_types_needed(&self) -> Vec { + let mut alignments = self + .generated_opaque_array + .borrow() + .iter() + .copied() + .collect::>(); + alignments.sort_unstable(); + alignments + } + + /// Call if a bindgen complex is generated + pub(crate) fn generated_bindgen_complex(&self) { + self.generated_bindgen_complex.set(true); + } + + /// Whether we need to generate the bindgen complex type + pub(crate) fn need_bindgen_complex_type(&self) -> bool { + self.generated_bindgen_complex.get() + } + + /// Call if a bindgen float16 is generated + pub(crate) fn generated_bindgen_float16(&self) { + self.generated_bindgen_float16.set(true); + } + + /// Whether we need to generate the bindgen float16 type + pub(crate) fn need_bindgen_float16_type(&self) -> bool { + self.generated_bindgen_float16.get() + } + + /// Compute which `enum`s have an associated `typedef` definition. + fn compute_enum_typedef_combos(&mut self) { + let _t = self.timer("compute_enum_typedef_combos"); + assert!(self.enum_typedef_combos.is_none()); + + let mut enum_typedef_combos = HashSet::default(); + for item in &self.items { + if let Some(ItemKind::Module(module)) = + item.as_ref().map(Item::kind) + { + // Find typedefs in this module, and build set of their names. + let mut names_of_typedefs = HashSet::default(); + for child_id in module.children() { + if let Some(ItemKind::Type(ty)) = + self.items[child_id.0].as_ref().map(Item::kind) + { + if let (Some(name), TypeKind::Alias(type_id)) = + (ty.name(), ty.kind()) + { + // We disregard aliases that refer to the enum + // itself, such as in `typedef enum { ... } Enum;`. + if type_id + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(self) + .expect_type() + .is_int() + { + names_of_typedefs.insert(name); + } + } + } + } + + // Find enums in this module, and record the ID of each one that + // has a typedef. + for child_id in module.children() { + if let Some(ItemKind::Type(ty)) = + self.items[child_id.0].as_ref().map(Item::kind) + { + if let (Some(name), true) = (ty.name(), ty.is_enum()) { + if names_of_typedefs.contains(name) { + enum_typedef_combos.insert(*child_id); + } + } + } + } + } + } + + self.enum_typedef_combos = Some(enum_typedef_combos); + } + + /// Look up whether `id` refers to an `enum` whose underlying type is + /// defined by a `typedef`. + pub(crate) fn is_enum_typedef_combo(&self, id: ItemId) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute enum_typedef_combos when we enter codegen", + ); + self.enum_typedef_combos.as_ref().unwrap().contains(&id) + } + + /// Compute whether we can derive debug. + fn compute_cannot_derive_debug(&mut self) { + let _t = self.timer("compute_cannot_derive_debug"); + assert!(self.cannot_derive_debug.is_none()); + if self.options.derive_debug { + self.cannot_derive_debug = + Some(as_cannot_derive_set(analyze::(( + self, + DeriveTrait::Debug, + )))); + } + } + + /// Look up whether the item with `id` can + /// derive debug or not. + pub(crate) fn lookup_can_derive_debug>( + &self, + id: Id, + ) -> bool { + let id = id.into(); + assert!( + self.in_codegen_phase(), + "We only compute can_derive_debug when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` can + // derive debug or not. + !self.cannot_derive_debug.as_ref().unwrap().contains(&id) + } + + /// Compute whether we can derive default. + fn compute_cannot_derive_default(&mut self) { + let _t = self.timer("compute_cannot_derive_default"); + assert!(self.cannot_derive_default.is_none()); + if self.options.derive_default { + self.cannot_derive_default = + Some(as_cannot_derive_set(analyze::(( + self, + DeriveTrait::Default, + )))); + } + } + + /// Look up whether the item with `id` can + /// derive default or not. + pub(crate) fn lookup_can_derive_default>( + &self, + id: Id, + ) -> bool { + let id = id.into(); + assert!( + self.in_codegen_phase(), + "We only compute can_derive_default when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` can + // derive default or not. + !self.cannot_derive_default.as_ref().unwrap().contains(&id) + } + + /// Compute whether we can derive copy. + fn compute_cannot_derive_copy(&mut self) { + let _t = self.timer("compute_cannot_derive_copy"); + assert!(self.cannot_derive_copy.is_none()); + self.cannot_derive_copy = + Some(as_cannot_derive_set(analyze::(( + self, + DeriveTrait::Copy, + )))); + } + + /// Compute whether we can derive hash. + fn compute_cannot_derive_hash(&mut self) { + let _t = self.timer("compute_cannot_derive_hash"); + assert!(self.cannot_derive_hash.is_none()); + if self.options.derive_hash { + self.cannot_derive_hash = + Some(as_cannot_derive_set(analyze::(( + self, + DeriveTrait::Hash, + )))); + } + } + + /// Look up whether the item with `id` can + /// derive hash or not. + pub(crate) fn lookup_can_derive_hash>( + &self, + id: Id, + ) -> bool { + let id = id.into(); + assert!( + self.in_codegen_phase(), + "We only compute can_derive_debug when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` can + // derive hash or not. + !self.cannot_derive_hash.as_ref().unwrap().contains(&id) + } + + /// Compute whether we can derive `PartialOrd`, `PartialEq` or `Eq`. + fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) { + let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq"); + assert!(self.cannot_derive_partialeq_or_partialord.is_none()); + if self.options.derive_partialord || + self.options.derive_partialeq || + self.options.derive_eq + { + self.cannot_derive_partialeq_or_partialord = + Some(analyze::(( + self, + DeriveTrait::PartialEqOrPartialOrd, + ))); + } + } + + /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`. + pub(crate) fn lookup_can_derive_partialeq_or_partialord< + Id: Into, + >( + &self, + id: Id, + ) -> CanDerive { + let id = id.into(); + assert!( + self.in_codegen_phase(), + "We only compute can_derive_partialeq_or_partialord when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` can + // derive partialeq or not. + self.cannot_derive_partialeq_or_partialord + .as_ref() + .unwrap() + .get(&id) + .copied() + .unwrap_or(CanDerive::Yes) + } + + /// Look up whether the item with `id` can derive `Copy` or not. + pub(crate) fn lookup_can_derive_copy>( + &self, + id: Id, + ) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute can_derive_debug when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` can + // derive `Copy` or not. + let id = id.into(); + + !self.lookup_has_type_param_in_array(id) && + !self.cannot_derive_copy.as_ref().unwrap().contains(&id) + } + + /// Compute whether the type has type parameter in array. + fn compute_has_type_param_in_array(&mut self) { + let _t = self.timer("compute_has_type_param_in_array"); + assert!(self.has_type_param_in_array.is_none()); + self.has_type_param_in_array = + Some(analyze::(self)); + } + + /// Look up whether the item with `id` has type parameter in array or not. + pub(crate) fn lookup_has_type_param_in_array>( + &self, + id: Id, + ) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute has array when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` has + // type parameter in array or not. + self.has_type_param_in_array + .as_ref() + .unwrap() + .contains(&id.into()) + } + + /// Compute whether the type has float. + fn compute_has_float(&mut self) { + let _t = self.timer("compute_has_float"); + assert!(self.has_float.is_none()); + if self.options.derive_eq || self.options.derive_ord { + self.has_float = Some(analyze::(self)); + } + } + + /// Look up whether the item with `id` has array or not. + pub(crate) fn lookup_has_float>(&self, id: Id) -> bool { + assert!( + self.in_codegen_phase(), + "We only compute has float when we enter codegen" + ); + + // Look up the computed value for whether the item with `id` has + // float or not. + self.has_float.as_ref().unwrap().contains(&id.into()) + } + + /// Check if `--no-partialeq` flag is enabled for this item. + pub(crate) fn no_partialeq_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().no_partialeq_types.matches(name) + } + + /// Check if `--no-copy` flag is enabled for this item. + pub(crate) fn no_copy_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().no_copy_types.matches(name) + } + + /// Check if `--no-debug` flag is enabled for this item. + pub(crate) fn no_debug_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().no_debug_types.matches(name) + } + + /// Check if `--no-default` flag is enabled for this item. + pub(crate) fn no_default_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().no_default_types.matches(name) + } + + /// Check if `--no-hash` flag is enabled for this item. + pub(crate) fn no_hash_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().no_hash_types.matches(name) + } + + /// Check if `--must-use-type` flag is enabled for this item. + pub(crate) fn must_use_type_by_name(&self, item: &Item) -> bool { + let name = item.path_for_allowlisting(self)[1..].join("::"); + self.options().must_use_types.matches(name) + } + + /// Wrap some tokens in an `unsafe` block if the `--wrap-unsafe-ops` option is enabled. + pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream { + if self.options.wrap_unsafe_ops { + quote!(unsafe { #tokens }) + } else { + tokens.into_token_stream() + } + } + + /// Get the suffix to be added to `static` functions if the `--wrap-static-fns` option is + /// enabled. + pub(crate) fn wrap_static_fns_suffix(&self) -> &str { + self.options() + .wrap_static_fns_suffix + .as_deref() + .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX) + } +} + +/// A builder struct for configuring item resolution options. +#[derive(Debug, Copy, Clone)] +pub(crate) struct ItemResolver { + id: ItemId, + through_type_refs: bool, + through_type_aliases: bool, +} + +impl ItemId { + /// Create an `ItemResolver` from this item ID. + pub(crate) fn into_resolver(self) -> ItemResolver { + self.into() + } +} + +impl From for ItemResolver +where + T: Into, +{ + fn from(id: T) -> ItemResolver { + ItemResolver::new(id) + } +} + +impl ItemResolver { + /// Construct a new `ItemResolver` from the given ID. + pub(crate) fn new>(id: Id) -> ItemResolver { + let id = id.into(); + ItemResolver { + id, + through_type_refs: false, + through_type_aliases: false, + } + } + + /// Keep resolving through `Type::TypeRef` items. + pub(crate) fn through_type_refs(mut self) -> ItemResolver { + self.through_type_refs = true; + self + } + + /// Keep resolving through `Type::Alias` items. + pub(crate) fn through_type_aliases(mut self) -> ItemResolver { + self.through_type_aliases = true; + self + } + + /// Finish configuring and perform the actual item resolution. + pub(crate) fn resolve(self, ctx: &BindgenContext) -> &Item { + assert!(ctx.collected_typerefs()); + + let mut id = self.id; + let mut seen_ids = HashSet::default(); + loop { + let item = ctx.resolve_item(id); + + // Detect cycles and bail out. These can happen in certain cases + // involving incomplete qualified dependent types (#2085). + if !seen_ids.insert(id) { + return item; + } + + let ty_kind = item.as_type().map(|t| t.kind()); + match ty_kind { + Some(&TypeKind::ResolvedTypeRef(next_id)) + if self.through_type_refs => + { + id = next_id.into(); + } + // We intentionally ignore template aliases here, as they are + // more complicated, and don't represent a simple renaming of + // some type. + Some(&TypeKind::Alias(next_id)) + if self.through_type_aliases => + { + id = next_id.into(); + } + _ => return item, + } + } + } +} + +/// A type that we are in the middle of parsing. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(crate) struct PartialType { + decl: Cursor, + // Just an ItemId, and not a TypeId, because we haven't finished this type + // yet, so there's still time for things to go wrong. + id: ItemId, +} + +impl PartialType { + /// Construct a new `PartialType`. + pub(crate) fn new(decl: Cursor, id: ItemId) -> PartialType { + // assert!(decl == decl.canonical()); + PartialType { decl, id } + } + + /// The cursor pointing to this partial type's declaration location. + pub(crate) fn decl(&self) -> &Cursor { + &self.decl + } + + /// The item ID allocated for this type. This is *NOT* a key for an entry in + /// the context's item set yet! + pub(crate) fn id(&self) -> ItemId { + self.id + } +} + +impl TemplateParameters for PartialType { + fn self_template_params(&self, _ctx: &BindgenContext) -> Vec { + // Maybe at some point we will eagerly parse named types, but for now we + // don't and this information is unavailable. + vec![] + } + + fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize { + // Wouldn't it be nice if libclang would reliably give us this + // information‽ + match self.decl().kind() { + clang_sys::CXCursor_ClassTemplate | + clang_sys::CXCursor_FunctionTemplate | + clang_sys::CXCursor_TypeAliasTemplateDecl => { + let mut num_params = 0; + self.decl().visit(|c| { + match c.kind() { + clang_sys::CXCursor_TemplateTypeParameter | + clang_sys::CXCursor_TemplateTemplateParameter | + clang_sys::CXCursor_NonTypeTemplateParameter => { + num_params += 1; + } + _ => {} + } + clang_sys::CXChildVisit_Continue + }); + num_params + } + _ => 0, + } + } +} + +fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) { + warn!("unused option: {name} {item}"); + + #[cfg(feature = "experimental")] + if _ctx.options().emit_diagnostics { + use crate::diagnostics::{Diagnostic, Level}; + + Diagnostic::default() + .with_title( + format!("Unused regular expression: `{item}`."), + Level::Warning, + ) + .add_annotation( + format!("This regular expression was passed to `{name}`."), + Level::Note, + ) + .display(); + } +} diff --git a/bindgen/ir/derive.rs b/bindgen/ir/derive.rs new file mode 100644 index 0000000000..3ee6476af9 --- /dev/null +++ b/bindgen/ir/derive.rs @@ -0,0 +1,130 @@ +//! Traits for determining whether we can derive traits for a thing or not. +//! +//! These traits tend to come in pairs: +//! +//! 1. A "trivial" version, whose implementations aren't allowed to recursively +//! look at other types or the results of fix point analyses. +//! +//! 2. A "normal" version, whose implementations simply query the results of a +//! fix point analysis. +//! +//! The former is used by the analyses when creating the results queried by the +//! second. + +use super::context::BindgenContext; + +use std::cmp; +use std::ops; + +/// A trait that encapsulates the logic for whether or not we can derive `Debug` +/// for a given thing. +pub(crate) trait CanDeriveDebug { + /// Return `true` if `Debug` can be derived for this thing, `false` + /// otherwise. + fn can_derive_debug(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive `Copy` +/// for a given thing. +pub(crate) trait CanDeriveCopy { + /// Return `true` if `Copy` can be derived for this thing, `false` + /// otherwise. + fn can_derive_copy(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive +/// `Default` for a given thing. +pub(crate) trait CanDeriveDefault { + /// Return `true` if `Default` can be derived for this thing, `false` + /// otherwise. + fn can_derive_default(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive `Hash` +/// for a given thing. +pub(crate) trait CanDeriveHash { + /// Return `true` if `Hash` can be derived for this thing, `false` + /// otherwise. + fn can_derive_hash(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive +/// `PartialEq` for a given thing. +pub(crate) trait CanDerivePartialEq { + /// Return `true` if `PartialEq` can be derived for this thing, `false` + /// otherwise. + fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive +/// `PartialOrd` for a given thing. +pub(crate) trait CanDerivePartialOrd { + /// Return `true` if `PartialOrd` can be derived for this thing, `false` + /// otherwise. + fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive `Eq` +/// for a given thing. +pub(crate) trait CanDeriveEq { + /// Return `true` if `Eq` can be derived for this thing, `false` otherwise. + fn can_derive_eq(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait that encapsulates the logic for whether or not we can derive `Ord` +/// for a given thing. +pub(crate) trait CanDeriveOrd { + /// Return `true` if `Ord` can be derived for this thing, `false` otherwise. + fn can_derive_ord(&self, ctx: &BindgenContext) -> bool; +} + +/// Whether it is possible or not to automatically derive trait for an item. +/// +/// ```ignore +/// No +/// ^ +/// | +/// Manually +/// ^ +/// | +/// Yes +/// ``` +/// +/// Initially we assume that we can derive trait for all types and then +/// update our understanding as we learn more about each type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)] +pub enum CanDerive { + /// Yes, we can derive automatically. + #[default] + Yes, + + /// The only thing that stops us from automatically deriving is that + /// array with more than maximum number of elements is used. + /// + /// This means we probably can "manually" implement such trait. + Manually, + + /// No, we cannot. + No, +} + +impl CanDerive { + /// Take the least upper bound of `self` and `rhs`. + pub(crate) fn join(self, rhs: Self) -> Self { + cmp::max(self, rhs) + } +} + +impl ops::BitOr for CanDerive { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + self.join(rhs) + } +} + +impl ops::BitOrAssign for CanDerive { + fn bitor_assign(&mut self, rhs: Self) { + *self = self.join(rhs); + } +} diff --git a/src/ir/dot.rs b/bindgen/ir/dot.rs similarity index 76% rename from src/ir/dot.rs rename to bindgen/ir/dot.rs index 48bd1d9164..9bfc559f41 100644 --- a/src/ir/dot.rs +++ b/bindgen/ir/dot.rs @@ -8,7 +8,7 @@ use std::path::Path; /// A trait for anything that can write attributes as `` rows to a dot /// file. -pub trait DotAttributes { +pub(crate) trait DotAttributes { /// Write this thing's attributes to the given output. Each attribute must /// be its own `...`. fn dot_attributes( @@ -17,11 +17,11 @@ pub trait DotAttributes { out: &mut W, ) -> io::Result<()> where - W: io::Write; + W: Write; } /// Write a graphviz dot file containing our IR. -pub fn write_dot_file

(ctx: &BindgenContext, path: P) -> io::Result<()> +pub(crate) fn write_dot_file

(ctx: &BindgenContext, path: P) -> io::Result<()> where P: AsRef, { @@ -32,20 +32,16 @@ where let mut err: Option> = None; for (id, item) in ctx.items() { - let is_whitelisted = ctx.whitelisted_items().contains(id); + let is_allowlisted = ctx.allowlisted_items().contains(&id); writeln!( &mut dot_file, r#"{} [fontname="courier", color={}, label=<

"#, id.as_usize(), - if is_whitelisted { - "black" - } else { - "gray" - } + if is_allowlisted { "black" } else { "gray" } )?; item.dot_attributes(ctx, &mut dot_file)?; - writeln!(&mut dot_file, r#"
>];"#)?; + writeln!(&mut dot_file, " >];")?; item.trace( ctx, @@ -56,15 +52,10 @@ where match writeln!( &mut dot_file, - "{} -> {} [label={:?}, color={}];", + "{} -> {} [label={edge_kind:?}, color={}];", id.as_usize(), sub_id.as_usize(), - edge_kind, - if is_whitelisted { - "black" - } else { - "gray" - } + if is_allowlisted { "black" } else { "gray" } ) { Ok(_) => {} Err(e) => err = Some(Err(e)), diff --git a/bindgen/ir/enum_ty.rs b/bindgen/ir/enum_ty.rs new file mode 100644 index 0000000000..9b08da3bce --- /dev/null +++ b/bindgen/ir/enum_ty.rs @@ -0,0 +1,321 @@ +//! Intermediate representation for C/C++ enumerations. + +use super::super::codegen::EnumVariation; +use super::context::{BindgenContext, TypeId}; +use super::item::Item; +use super::ty::{Type, TypeKind}; +use crate::clang; +use crate::ir::annotations::Annotations; +use crate::parse::ParseError; +use crate::regex_set::RegexSet; + +/// An enum representing custom handling that can be given to a variant. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum EnumVariantCustomBehavior { + /// This variant will be a module containing constants. + ModuleConstify, + /// This variant will be constified, that is, forced to generate a constant. + Constify, + /// This variant will be hidden entirely from the resulting enum. + Hide, +} + +/// A C/C++ enumeration. +#[derive(Debug)] +pub(crate) struct Enum { + /// The representation used for this enum; it should be an `IntKind` type or + /// an alias to one. + /// + /// It's `None` if the enum is a forward declaration and isn't defined + /// anywhere else, see `tests/headers/func_ptr_in_struct.h`. + repr: Option, + + /// The different variants, with explicit values. + variants: Vec, +} + +impl Enum { + /// Construct a new `Enum` with the given representation and variants. + pub(crate) fn new( + repr: Option, + variants: Vec, + ) -> Self { + Enum { repr, variants } + } + + /// Get this enumeration's representation. + pub(crate) fn repr(&self) -> Option { + self.repr + } + + /// Get this enumeration's variants. + pub(crate) fn variants(&self) -> &[EnumVariant] { + &self.variants + } + + /// Construct an enumeration from the given Clang type. + pub(crate) fn from_ty( + ty: &clang::Type, + ctx: &mut BindgenContext, + ) -> Result { + use clang_sys::*; + debug!("Enum::from_ty {ty:?}"); + + if ty.kind() != CXType_Enum { + return Err(ParseError::Continue); + } + + let declaration = ty.declaration().canonical(); + let repr = declaration + .enum_type() + .and_then(|et| Item::from_ty(&et, declaration, None, ctx).ok()); + let mut variants = vec![]; + + let variant_ty = + repr.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx)); + let is_bool = variant_ty.is_some_and(Type::is_bool); + + // Assume signedness since the default type by the C standard is an int. + let is_signed = variant_ty.map_or(true, |ty| match *ty.kind() { + TypeKind::Int(ref int_kind) => int_kind.is_signed(), + ref other => { + panic!("Since when enums can be non-integers? {other:?}") + } + }); + + let type_name = ty.spelling(); + let type_name = if type_name.is_empty() { + None + } else { + Some(type_name) + }; + let type_name = type_name.as_deref(); + + let definition = declaration.definition().unwrap_or(declaration); + definition.visit(|cursor| { + if cursor.kind() == CXCursor_EnumConstantDecl { + let value = if is_bool { + cursor.enum_val_boolean().map(EnumVariantValue::Boolean) + } else if is_signed { + cursor.enum_val_signed().map(EnumVariantValue::Signed) + } else { + cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned) + }; + if let Some(val) = value { + let name = cursor.spelling(); + let annotations = Annotations::new(&cursor); + let custom_behavior = ctx + .options() + .last_callback(|callbacks| { + callbacks + .enum_variant_behavior(type_name, &name, val) + }) + .or_else(|| { + let annotations = annotations.as_ref()?; + if annotations.hide() { + Some(EnumVariantCustomBehavior::Hide) + } else if annotations.constify_enum_variant() { + Some(EnumVariantCustomBehavior::Constify) + } else { + None + } + }); + + let new_name = ctx + .options() + .last_callback(|callbacks| { + callbacks.enum_variant_name(type_name, &name, val) + }) + .or_else(|| { + annotations + .as_ref()? + .use_instead_of()? + .last() + .cloned() + }) + .unwrap_or_else(|| name.clone()); + + let comment = cursor.raw_comment(); + variants.push(EnumVariant::new( + new_name, + name, + comment, + val, + custom_behavior, + )); + } + } + CXChildVisit_Continue + }); + Ok(Enum::new(repr, variants)) + } + + fn is_matching_enum( + &self, + ctx: &BindgenContext, + enums: &RegexSet, + item: &Item, + ) -> bool { + let path = item.path_for_allowlisting(ctx); + let enum_ty = item.expect_type(); + + if enums.matches(path[1..].join("::")) { + return true; + } + + // Test the variants if the enum is anonymous. + if enum_ty.name().is_some() { + return false; + } + + self.variants().iter().any(|v| enums.matches(v.name())) + } + + /// Returns the final representation of the enum. + pub(crate) fn computed_enum_variation( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> EnumVariation { + // ModuleConsts has higher precedence before Rust in order to avoid + // problems with overlapping match patterns. + if self.is_matching_enum( + ctx, + &ctx.options().constified_enum_modules, + item, + ) { + EnumVariation::ModuleConsts + } else if self.is_matching_enum( + ctx, + &ctx.options().bitfield_enums, + item, + ) { + EnumVariation::NewType { + is_bitfield: true, + is_global: false, + } + } else if self.is_matching_enum(ctx, &ctx.options().newtype_enums, item) + { + EnumVariation::NewType { + is_bitfield: false, + is_global: false, + } + } else if self.is_matching_enum( + ctx, + &ctx.options().newtype_global_enums, + item, + ) { + EnumVariation::NewType { + is_bitfield: false, + is_global: true, + } + } else if self.is_matching_enum( + ctx, + &ctx.options().rustified_enums, + item, + ) { + EnumVariation::Rust { + non_exhaustive: false, + } + } else if self.is_matching_enum( + ctx, + &ctx.options().rustified_non_exhaustive_enums, + item, + ) { + EnumVariation::Rust { + non_exhaustive: true, + } + } else if self.is_matching_enum( + ctx, + &ctx.options().constified_enums, + item, + ) { + EnumVariation::Consts + } else { + ctx.options().default_enum_style + } + } +} + +/// A single enum variant, to be contained only in an enum. +#[derive(Debug)] +pub(crate) struct EnumVariant { + /// The name of the variant. + name: String, + + /// The original name of the variant (without user mangling) + name_for_allowlisting: String, + + /// An optional doc comment. + comment: Option, + + /// The integer value of the variant. + val: EnumVariantValue, + + /// The custom behavior this variant may have, if any. + custom_behavior: Option, +} + +/// A constant value assigned to an enumeration variant. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum EnumVariantValue { + /// A boolean constant. + Boolean(bool), + + /// A signed constant. + Signed(i64), + + /// An unsigned constant. + Unsigned(u64), +} + +impl EnumVariant { + /// Construct a new enumeration variant from the given parts. + pub(crate) fn new( + name: String, + name_for_allowlisting: String, + comment: Option, + val: EnumVariantValue, + custom_behavior: Option, + ) -> Self { + EnumVariant { + name, + name_for_allowlisting, + comment, + val, + custom_behavior, + } + } + + /// Get this variant's name. + pub(crate) fn name(&self) -> &str { + &self.name + } + + /// Get this variant's name. + pub(crate) fn name_for_allowlisting(&self) -> &str { + &self.name_for_allowlisting + } + + /// Get this variant's value. + pub(crate) fn val(&self) -> EnumVariantValue { + self.val + } + + /// Get this variant's documentation. + pub(crate) fn comment(&self) -> Option<&str> { + self.comment.as_deref() + } + + /// Returns whether this variant should be enforced to be a constant by code + /// generation. + pub(crate) fn force_constification(&self) -> bool { + self.custom_behavior == Some(EnumVariantCustomBehavior::Constify) + } + + /// Returns whether the current variant should be hidden completely from the + /// resulting rust enum. + pub(crate) fn hidden(&self) -> bool { + self.custom_behavior == Some(EnumVariantCustomBehavior::Hide) + } +} diff --git a/bindgen/ir/function.rs b/bindgen/ir/function.rs new file mode 100644 index 0000000000..6f8c00fa89 --- /dev/null +++ b/bindgen/ir/function.rs @@ -0,0 +1,837 @@ +//! Intermediate representation for C/C++ functions and methods. + +use super::comp::MethodKind; +use super::context::{BindgenContext, TypeId}; +use super::dot::DotAttributes; +use super::item::Item; +use super::traversal::{EdgeKind, Trace, Tracer}; +use super::ty::TypeKind; +use crate::callbacks::{ItemInfo, ItemKind}; +use crate::clang::{self, ABIKind, Attribute}; +use crate::parse::{ClangSubItemParser, ParseError, ParseResult}; +use clang_sys::CXCallingConv; + +use quote::TokenStreamExt; +use std::io; +use std::str::FromStr; + +const RUST_DERIVE_FUNPTR_LIMIT: usize = 12; + +/// What kind of function are we looking at? +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum FunctionKind { + /// A plain, free function. + Function, + /// A method of some kind. + Method(MethodKind), +} + +impl FunctionKind { + /// Given a clang cursor, return the kind of function it represents, or + /// `None` otherwise. + pub(crate) fn from_cursor(cursor: &clang::Cursor) -> Option { + // FIXME(emilio): Deduplicate logic with `ir::comp`. + Some(match cursor.kind() { + clang_sys::CXCursor_FunctionDecl => FunctionKind::Function, + clang_sys::CXCursor_Constructor => { + FunctionKind::Method(MethodKind::Constructor) + } + clang_sys::CXCursor_Destructor => { + FunctionKind::Method(if cursor.method_is_virtual() { + MethodKind::VirtualDestructor { + pure_virtual: cursor.method_is_pure_virtual(), + } + } else { + MethodKind::Destructor + }) + } + clang_sys::CXCursor_CXXMethod => { + if cursor.method_is_virtual() { + FunctionKind::Method(MethodKind::Virtual { + pure_virtual: cursor.method_is_pure_virtual(), + }) + } else if cursor.method_is_static() { + FunctionKind::Method(MethodKind::Static) + } else { + FunctionKind::Method(MethodKind::Normal) + } + } + _ => return None, + }) + } +} + +/// The style of linkage +#[derive(Debug, Clone, Copy)] +pub(crate) enum Linkage { + /// Externally visible and can be linked against + External, + /// Not exposed externally. 'static inline' functions will have this kind of linkage + Internal, +} + +/// A function declaration, with a signature, arguments, and argument names. +/// +/// The argument names vector must be the same length as the ones in the +/// signature. +#[derive(Debug)] +pub(crate) struct Function { + /// The name of this function. + name: String, + + /// The mangled name, that is, the symbol. + mangled_name: Option, + + /// The link name. If specified, overwrite `mangled_name`. + link_name: Option, + + /// The ID pointing to the current function signature. + signature: TypeId, + + /// The kind of function this is. + kind: FunctionKind, + + /// The linkage of the function. + linkage: Linkage, +} + +impl Function { + /// Construct a new function. + pub(crate) fn new( + name: String, + mangled_name: Option, + link_name: Option, + signature: TypeId, + kind: FunctionKind, + linkage: Linkage, + ) -> Self { + Function { + name, + mangled_name, + link_name, + signature, + kind, + linkage, + } + } + + /// Get this function's name. + pub(crate) fn name(&self) -> &str { + &self.name + } + + /// Get this function's name. + pub(crate) fn mangled_name(&self) -> Option<&str> { + self.mangled_name.as_deref() + } + + /// Get this function's link name. + pub fn link_name(&self) -> Option<&str> { + self.link_name.as_deref() + } + + /// Get this function's signature type. + pub(crate) fn signature(&self) -> TypeId { + self.signature + } + + /// Get this function's kind. + pub(crate) fn kind(&self) -> FunctionKind { + self.kind + } + + /// Get this function's linkage. + pub(crate) fn linkage(&self) -> Linkage { + self.linkage + } +} + +impl DotAttributes for Function { + fn dot_attributes( + &self, + _ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + if let Some(ref mangled) = self.mangled_name { + let mangled: String = + mangled.chars().flat_map(|c| c.escape_default()).collect(); + writeln!(out, "mangled name{mangled}")?; + } + + Ok(()) + } +} + +/// A valid rust ABI. +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +pub enum Abi { + /// The default C ABI. + C, + /// The "stdcall" ABI. + Stdcall, + /// The "efiapi" ABI. + EfiApi, + /// The "fastcall" ABI. + Fastcall, + /// The "thiscall" ABI. + ThisCall, + /// The "vectorcall" ABI. + Vectorcall, + /// The "aapcs" ABI. + Aapcs, + /// The "win64" ABI. + Win64, + /// The "C-unwind" ABI. + CUnwind, + /// The "system" ABI. + System, +} + +impl FromStr for Abi { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "C" => Ok(Self::C), + "stdcall" => Ok(Self::Stdcall), + "efiapi" => Ok(Self::EfiApi), + "fastcall" => Ok(Self::Fastcall), + "thiscall" => Ok(Self::ThisCall), + "vectorcall" => Ok(Self::Vectorcall), + "aapcs" => Ok(Self::Aapcs), + "win64" => Ok(Self::Win64), + "C-unwind" => Ok(Self::CUnwind), + "system" => Ok(Self::System), + _ => Err(format!("Invalid or unknown ABI {s:?}")), + } + } +} + +impl std::fmt::Display for Abi { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match *self { + Self::C => "C", + Self::Stdcall => "stdcall", + Self::EfiApi => "efiapi", + Self::Fastcall => "fastcall", + Self::ThisCall => "thiscall", + Self::Vectorcall => "vectorcall", + Self::Aapcs => "aapcs", + Self::Win64 => "win64", + Self::CUnwind => "C-unwind", + Abi::System => "system", + }; + + s.fmt(f) + } +} + +impl quote::ToTokens for Abi { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let abi = self.to_string(); + tokens.append_all(quote! { #abi }); + } +} + +/// An ABI extracted from a clang cursor. +#[derive(Debug, Copy, Clone)] +pub(crate) enum ClangAbi { + /// An ABI known by Rust. + Known(Abi), + /// An unknown or invalid ABI. + Unknown(CXCallingConv), +} + +impl ClangAbi { + /// Returns whether this Abi is known or not. + fn is_unknown(self) -> bool { + matches!(self, ClangAbi::Unknown(..)) + } +} + +impl quote::ToTokens for ClangAbi { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match *self { + Self::Known(abi) => abi.to_tokens(tokens), + Self::Unknown(cc) => panic!( + "Cannot turn unknown calling convention to tokens: {cc:?}" + ), + } + } +} + +/// A function signature. +#[derive(Debug)] +pub(crate) struct FunctionSig { + /// The name of this function signature. + name: String, + + /// The return type of the function. + return_type: TypeId, + + /// The type of the arguments, optionally with the name of the argument when + /// declared. + argument_types: Vec<(Option, TypeId)>, + + /// Whether this function is variadic. + is_variadic: bool, + is_divergent: bool, + + /// Whether this function's return value must be used. + must_use: bool, + + /// The ABI of this function. + abi: ClangAbi, +} + +fn get_abi(cc: CXCallingConv) -> ClangAbi { + use clang_sys::*; + match cc { + CXCallingConv_Default | CXCallingConv_C => ClangAbi::Known(Abi::C), + CXCallingConv_X86StdCall => ClangAbi::Known(Abi::Stdcall), + CXCallingConv_X86FastCall => ClangAbi::Known(Abi::Fastcall), + CXCallingConv_X86ThisCall => ClangAbi::Known(Abi::ThisCall), + CXCallingConv_X86VectorCall | CXCallingConv_AArch64VectorCall => { + ClangAbi::Known(Abi::Vectorcall) + } + CXCallingConv_AAPCS => ClangAbi::Known(Abi::Aapcs), + CXCallingConv_X86_64Win64 => ClangAbi::Known(Abi::Win64), + other => ClangAbi::Unknown(other), + } +} + +/// Get the mangled name for the cursor's referent. +pub(crate) fn cursor_mangling( + ctx: &BindgenContext, + cursor: &clang::Cursor, +) -> Option { + if !ctx.options().enable_mangling { + return None; + } + + // We early return here because libclang may crash in some case + // if we pass in a variable inside a partial specialized template. + // See rust-lang/rust-bindgen#67, and rust-lang/rust-bindgen#462. + if cursor.is_in_non_fully_specialized_template() { + return None; + } + + let is_itanium_abi = ctx.abi_kind() == ABIKind::GenericItanium; + let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor; + if let Ok(mut manglings) = cursor.cxx_manglings() { + while let Some(m) = manglings.pop() { + // Only generate the destructor group 1, see below. + if is_itanium_abi && is_destructor && !m.ends_with("D1Ev") { + continue; + } + + return Some(m); + } + } + + let mut mangling = cursor.mangling(); + if mangling.is_empty() { + return None; + } + + if is_itanium_abi && is_destructor { + // With old (3.8-) libclang versions, and the Itanium ABI, clang returns + // the "destructor group 0" symbol, which means that it'll try to free + // memory, which definitely isn't what we want. + // + // Explicitly force the destructor group 1 symbol. + // + // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special + // for the reference, and http://stackoverflow.com/a/6614369/1091587 for + // a more friendly explanation. + // + // We don't need to do this for constructors since clang seems to always + // have returned the C1 constructor. + // + // FIXME(emilio): Can a legit symbol in other ABIs end with this string? + // I don't think so, but if it can this would become a linker error + // anyway, not an invalid free at runtime. + // + // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with + // time. + if mangling.ends_with("D0Ev") { + let new_len = mangling.len() - 4; + mangling.truncate(new_len); + mangling.push_str("D1Ev"); + } + } + + Some(mangling) +} + +fn args_from_ty_and_cursor( + ty: &clang::Type, + cursor: &clang::Cursor, + ctx: &mut BindgenContext, +) -> Vec<(Option, TypeId)> { + let cursor_args = cursor.args().unwrap_or_default().into_iter(); + let type_args = ty.args().unwrap_or_default().into_iter(); + + // Argument types can be found in either the cursor or the type, but argument names may only be + // found on the cursor. We often have access to both a type and a cursor for each argument, but + // in some cases we may only have one. + // + // Prefer using the type as the source of truth for the argument's type, but fall back to + // inspecting the cursor (this happens for Objective C interfaces). + // + // Prefer using the cursor for the argument's type, but fall back to using the parent's cursor + // (this happens for function pointer return types). + cursor_args + .map(Some) + .chain(std::iter::repeat(None)) + .zip(type_args.map(Some).chain(std::iter::repeat(None))) + .take_while(|(cur, ty)| cur.is_some() || ty.is_some()) + .map(|(arg_cur, arg_ty)| { + let name = arg_cur.map(|a| a.spelling()).and_then(|name| { + if name.is_empty() { + None + } else { + Some(name) + } + }); + + let cursor = arg_cur.unwrap_or(*cursor); + let ty = arg_ty.unwrap_or_else(|| cursor.cur_type()); + (name, Item::from_ty_or_ref(ty, cursor, None, ctx)) + }) + .collect() +} + +impl FunctionSig { + /// Get the function name. + pub(crate) fn name(&self) -> &str { + &self.name + } + + /// Construct a new function signature from the given Clang type. + pub(crate) fn from_ty( + ty: &clang::Type, + cursor: &clang::Cursor, + ctx: &mut BindgenContext, + ) -> Result { + use clang_sys::*; + debug!("FunctionSig::from_ty {ty:?} {cursor:?}"); + + // Skip function templates + let kind = cursor.kind(); + if kind == CXCursor_FunctionTemplate { + return Err(ParseError::Continue); + } + + let spelling = cursor.spelling(); + + // Don't parse operatorxx functions in C++ + let is_operator = |spelling: &str| { + spelling.starts_with("operator") && + !clang::is_valid_identifier(spelling) + }; + if is_operator(&spelling) && !ctx.options().represent_cxx_operators { + return Err(ParseError::Continue); + } + + // Constructors of non-type template parameter classes for some reason + // include the template parameter in their name. Just skip them, since + // we don't handle well non-type template parameters anyway. + if (kind == CXCursor_Constructor || kind == CXCursor_Destructor) && + spelling.contains('<') + { + return Err(ParseError::Continue); + } + + let cursor = if cursor.is_valid() { + *cursor + } else { + ty.declaration() + }; + + let mut args = match kind { + CXCursor_FunctionDecl | + CXCursor_Constructor | + CXCursor_CXXMethod | + CXCursor_ObjCInstanceMethodDecl | + CXCursor_ObjCClassMethodDecl => { + args_from_ty_and_cursor(ty, &cursor, ctx) + } + _ => { + // For non-CXCursor_FunctionDecl, visiting the cursor's children + // is the only reliable way to get parameter names. + let mut args = vec![]; + cursor.visit(|c| { + if c.kind() == CXCursor_ParmDecl { + let ty = + Item::from_ty_or_ref(c.cur_type(), c, None, ctx); + let name = c.spelling(); + let name = + if name.is_empty() { None } else { Some(name) }; + args.push((name, ty)); + } + CXChildVisit_Continue + }); + + if args.is_empty() { + // FIXME(emilio): Sometimes libclang doesn't expose the + // right AST for functions tagged as stdcall and such... + // + // https://bugs.llvm.org/show_bug.cgi?id=45919 + args_from_ty_and_cursor(ty, &cursor, ctx) + } else { + args + } + } + }; + + let (must_use, mut is_divergent) = + if ctx.options().enable_function_attribute_detection { + let [must_use, no_return, no_return_cpp] = cursor.has_attrs(&[ + Attribute::MUST_USE, + Attribute::NO_RETURN, + Attribute::NO_RETURN_CPP, + ]); + (must_use, no_return || no_return_cpp) + } else { + Default::default() + }; + + // Check if the type contains __attribute__((noreturn)) outside of parentheses. This is + // somewhat fragile, but it seems to be the only way to get at this information as of + // libclang 9. + let ty_spelling = ty.spelling(); + let has_attribute_noreturn = ty_spelling + .match_indices("__attribute__((noreturn))") + .any(|(i, _)| { + let depth = ty_spelling[..i] + .bytes() + .filter_map(|ch| match ch { + b'(' => Some(1), + b')' => Some(-1), + _ => None, + }) + .sum::(); + depth == 0 + }); + is_divergent = is_divergent || has_attribute_noreturn; + + let is_method = kind == CXCursor_CXXMethod; + let is_constructor = kind == CXCursor_Constructor; + let is_destructor = kind == CXCursor_Destructor; + if (is_constructor || is_destructor || is_method) && + cursor.lexical_parent() != cursor.semantic_parent() + { + // Only parse constructors once. + return Err(ParseError::Continue); + } + + if is_method || is_constructor || is_destructor { + let is_const = is_method && cursor.method_is_const(); + let is_virtual = is_method && cursor.method_is_virtual(); + let is_static = is_method && cursor.method_is_static(); + if !is_static && + (!is_virtual || + ctx.options().use_specific_virtual_function_receiver) + { + let parent = cursor.semantic_parent(); + let class = Item::parse(parent, None, ctx) + .expect("Expected to parse the class"); + // The `class` most likely is not finished parsing yet, so use + // the unchecked variant. + let class = class.as_type_id_unchecked(); + + let class = if is_const { + let const_class_id = ctx.next_item_id(); + ctx.build_const_wrapper( + const_class_id, + class, + None, + &parent.cur_type(), + ) + } else { + class + }; + + let ptr = + Item::builtin_type(TypeKind::Pointer(class), false, ctx); + args.insert(0, (Some("this".into()), ptr)); + } else if is_virtual { + let void = Item::builtin_type(TypeKind::Void, false, ctx); + let ptr = + Item::builtin_type(TypeKind::Pointer(void), false, ctx); + args.insert(0, (Some("this".into()), ptr)); + } + } + + let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl || + kind == CXCursor_ObjCClassMethodDecl + { + ty.ret_type() + .or_else(|| cursor.ret_type()) + .ok_or(ParseError::Continue)? + } else { + ty.ret_type().ok_or(ParseError::Continue)? + }; + + let ret = if is_constructor && ctx.is_target_wasm32() { + // Constructors in Clang wasm32 target return a pointer to the object + // being constructed. + let void = Item::builtin_type(TypeKind::Void, false, ctx); + Item::builtin_type(TypeKind::Pointer(void), false, ctx) + } else { + Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx) + }; + + // Clang plays with us at "find the calling convention", see #549 and + // co. This seems to be a better fix than that commit. + let mut call_conv = ty.call_conv(); + if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() { + let cursor_call_conv = ty.call_conv(); + if cursor_call_conv != CXCallingConv_Invalid { + call_conv = cursor_call_conv; + } + } + + let abi = get_abi(call_conv); + + if abi.is_unknown() { + warn!("Unknown calling convention: {call_conv:?}"); + } + + Ok(Self { + name: spelling, + return_type: ret, + argument_types: args, + is_variadic: ty.is_variadic(), + is_divergent, + must_use, + abi, + }) + } + + /// Get this function signature's return type. + pub(crate) fn return_type(&self) -> TypeId { + self.return_type + } + + /// Get this function signature's argument (name, type) pairs. + pub(crate) fn argument_types(&self) -> &[(Option, TypeId)] { + &self.argument_types + } + + /// Get this function signature's ABI. + pub(crate) fn abi( + &self, + ctx: &BindgenContext, + name: Option<&str>, + ) -> crate::codegen::error::Result { + // FIXME (pvdrz): Try to do this check lazily instead. Maybe store the ABI inside `ctx` + // instead?. + let abi = if let Some(name) = name { + if let Some((abi, _)) = ctx + .options() + .abi_overrides + .iter() + .find(|(_, regex_set)| regex_set.matches(name)) + { + ClangAbi::Known(*abi) + } else { + self.abi + } + } else if let Some((abi, _)) = ctx + .options() + .abi_overrides + .iter() + .find(|(_, regex_set)| regex_set.matches(&self.name)) + { + ClangAbi::Known(*abi) + } else { + self.abi + }; + + match abi { + ClangAbi::Known(Abi::ThisCall) + if !ctx.options().rust_features().thiscall_abi => + { + Err(crate::codegen::error::Error::UnsupportedAbi("thiscall")) + } + ClangAbi::Known(Abi::Vectorcall) + if !ctx.options().rust_features().vectorcall_abi => + { + Err(crate::codegen::error::Error::UnsupportedAbi("vectorcall")) + } + ClangAbi::Known(Abi::CUnwind) + if !ctx.options().rust_features().c_unwind_abi => + { + Err(crate::codegen::error::Error::UnsupportedAbi("C-unwind")) + } + ClangAbi::Known(Abi::EfiApi) + if !ctx.options().rust_features().abi_efiapi => + { + Err(crate::codegen::error::Error::UnsupportedAbi("efiapi")) + } + ClangAbi::Known(Abi::Win64) if self.is_variadic() => { + Err(crate::codegen::error::Error::UnsupportedAbi("Win64")) + } + abi => Ok(abi), + } + } + + /// Is this function signature variadic? + pub(crate) fn is_variadic(&self) -> bool { + // Clang reports some functions as variadic when they *might* be + // variadic. We do the argument check because rust doesn't codegen well + // variadic functions without an initial argument. + self.is_variadic && !self.argument_types.is_empty() + } + + /// Must this function's return value be used? + pub(crate) fn must_use(&self) -> bool { + self.must_use + } + + /// Are function pointers with this signature able to derive Rust traits? + /// Rust only supports deriving traits for function pointers with a limited + /// number of parameters and a couple ABIs. + /// + /// For more details, see: + /// + /// * , + /// * , + /// * and + pub(crate) fn function_pointers_can_derive(&self) -> bool { + if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { + return false; + } + + matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..)) + } + + /// Whether this function has attributes marking it as divergent. + pub(crate) fn is_divergent(&self) -> bool { + self.is_divergent + } +} + +impl ClangSubItemParser for Function { + fn parse( + cursor: clang::Cursor, + context: &mut BindgenContext, + ) -> Result, ParseError> { + use clang_sys::*; + + let Some(kind) = FunctionKind::from_cursor(&cursor) else { + return Err(ParseError::Continue); + }; + + debug!("Function::parse({cursor:?}, {:?})", cursor.cur_type()); + let visibility = cursor.visibility(); + if visibility != CXVisibility_Default { + return Err(ParseError::Continue); + } + if cursor.access_specifier() == CX_CXXPrivate && + !context.options().generate_private_functions + { + return Err(ParseError::Continue); + } + + let linkage = cursor.linkage(); + let linkage = match linkage { + CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External, + CXLinkage_Internal => Linkage::Internal, + _ => return Err(ParseError::Continue), + }; + + if cursor.is_inlined_function() || + cursor.definition().is_some_and(|x| x.is_inlined_function()) + { + if !context.options().generate_inline_functions && + !context.options().wrap_static_fns + { + return Err(ParseError::Continue); + } + + if cursor.is_deleted_function() && + !context.options().generate_deleted_functions + { + return Err(ParseError::Continue); + } + + // We cannot handle `inline` functions that are not `static`. + if context.options().wrap_static_fns && + cursor.is_inlined_function() && + matches!(linkage, Linkage::External) + { + return Err(ParseError::Continue); + } + } + + // Grab the signature using Item::from_ty. + let sig = Item::from_ty(&cursor.cur_type(), cursor, None, context)?; + + let mut name = cursor.spelling(); + assert!(!name.is_empty(), "Empty function name?"); + + if cursor.kind() == CXCursor_Destructor { + // Remove the leading `~`. The alternative to this is special-casing + // code-generation for destructor functions, which seems less than + // ideal. + if name.starts_with('~') { + name.remove(0); + } + + // Add a suffix to avoid colliding with constructors. This would be + // technically fine (since we handle duplicated functions/methods), + // but seems easy enough to handle it here. + name.push_str("_destructor"); + } + if let Some(nm) = context.options().last_callback(|callbacks| { + callbacks.generated_name_override(ItemInfo { + name: name.as_str(), + kind: ItemKind::Function, + }) + }) { + name = nm; + } + assert!(!name.is_empty(), "Empty function name."); + + let mangled_name = cursor_mangling(context, &cursor); + + let link_name = context.options().last_callback(|callbacks| { + callbacks.generated_link_name_override(ItemInfo { + name: name.as_str(), + kind: ItemKind::Function, + }) + }); + + let function = Self::new( + name.clone(), + mangled_name, + link_name, + sig, + kind, + linkage, + ); + + Ok(ParseResult::New(function, Some(cursor))) + } +} + +impl Trace for FunctionSig { + type Extra = (); + + fn trace(&self, _: &BindgenContext, tracer: &mut T, _: &()) + where + T: Tracer, + { + tracer.visit_kind(self.return_type().into(), EdgeKind::FunctionReturn); + + for &(_, ty) in self.argument_types() { + tracer.visit_kind(ty.into(), EdgeKind::FunctionParameter); + } + } +} diff --git a/src/ir/int.rs b/bindgen/ir/int.rs similarity index 75% rename from src/ir/int.rs rename to bindgen/ir/int.rs index b7f0f0c54d..217fc11efa 100644 --- a/src/ir/int.rs +++ b/bindgen/ir/int.rs @@ -12,6 +12,9 @@ pub enum IntKind { /// An `unsigned char`. UChar, + /// A `wchar_t`. + WChar, + /// A platform-dependent `char` type, with the signedness support. Char { /// Whether the char is signed for the target platform. @@ -51,9 +54,12 @@ pub enum IntKind { /// A 16-bit signed integer. I16, - /// Either a `char16_t` or a `wchar_t`. + /// A 16-bit integer, used only for enum size representation. U16, + /// The C++ type `char16_t`, which is its own type (unlike in C). + Char16, + /// A 32-bit signed integer. I32, @@ -84,49 +90,34 @@ pub enum IntKind { impl IntKind { /// Is this integral type signed? - pub fn is_signed(&self) -> bool { + pub(crate) fn is_signed(&self) -> bool { use self::IntKind::*; match *self { + // TODO(emilio): wchar_t can in theory be signed, but we have no way + // to know whether it is or not right now (unlike char, there's no + // WChar_S / WChar_U). Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 | - U32 | U64 | U128 => false, + Char16 | WChar | U32 | U64 | U128 => false, SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 | I128 => true, - Char { - is_signed, - } => is_signed, - - Custom { - is_signed, .. - } => is_signed, + Char { is_signed } | Custom { is_signed, .. } => is_signed, } } /// If this type has a known size, return it (in bytes). This is to /// alleviate libclang sometimes not giving us a layout (like in the case /// when an enum is defined inside a class with template parameters). - pub fn known_size(&self) -> Option { + pub(crate) fn known_size(&self) -> Option { use self::IntKind::*; Some(match *self { - Bool | - UChar | - SChar | - U8 | - I8 | - Char { - .. - } => 1, - U16 | I16 => 2, + Bool | UChar | SChar | U8 | I8 | Char { .. } => 1, + U16 | I16 | Char16 => 2, U32 | I32 => 4, U64 | I64 => 8, I128 | U128 => 16, _ => return None, }) } - - /// Whether this type's signedness matches the value. - pub fn signedness_matches(&self, val: i64) -> bool { - val >= 0 || self.is_signed() - } } diff --git a/bindgen/ir/item.rs b/bindgen/ir/item.rs new file mode 100644 index 0000000000..eea02cce6c --- /dev/null +++ b/bindgen/ir/item.rs @@ -0,0 +1,2005 @@ +//! Bindgen's core intermediate representation type. + +use super::super::codegen::{ + AliasVariation, EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME, +}; +use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult}; +use super::annotations::Annotations; +use super::comp::{CompKind, MethodKind}; +use super::context::{BindgenContext, ItemId, PartialType, TypeId}; +use super::derive::{ + CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq, + CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd, +}; +use super::dot::DotAttributes; +use super::function::{Function, FunctionKind}; +use super::item_kind::ItemKind; +use super::module::Module; +use super::template::{AsTemplateParam, TemplateParameters}; +use super::traversal::{EdgeKind, Trace, Tracer}; +use super::ty::{Type, TypeKind}; +use crate::callbacks::ItemInfo; +use crate::clang; +use crate::parse::{ClangSubItemParser, ParseError, ParseResult}; + +use std::cell::{Cell, OnceCell}; +use std::collections::BTreeSet; +use std::fmt::Write; +use std::io; +use std::iter; +use std::sync::OnceLock; + +/// A trait to get the canonical name from an item. +/// +/// This is the trait that will eventually isolate all the logic related to name +/// mangling and that kind of stuff. +/// +/// This assumes no nested paths, at some point I'll have to make it a more +/// complex thing. +/// +/// This name is required to be safe for Rust, that is, is not expected to +/// return any rust keyword from here. +pub(crate) trait ItemCanonicalName { + /// Get the canonical name for this item. + fn canonical_name(&self, ctx: &BindgenContext) -> String; +} + +/// The same, but specifies the path that needs to be followed to reach an item. +/// +/// To contrast with `canonical_name`, here's an example: +/// +/// ```c++ +/// namespace foo { +/// const BAR = 3; +/// } +/// ``` +/// +/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical +/// name is just `"BAR"`. +pub(crate) trait ItemCanonicalPath { + /// Get the namespace-aware canonical path for this item. This means that if + /// namespaces are disabled, you'll get a single item, and otherwise you get + /// the whole path. + fn namespace_aware_canonical_path( + &self, + ctx: &BindgenContext, + ) -> Vec; + + /// Get the canonical path for this item. + fn canonical_path(&self, ctx: &BindgenContext) -> Vec; +} + +/// A trait for determining if some IR thing is opaque or not. +pub(crate) trait IsOpaque { + /// Extra context the IR thing needs to determine if it is opaque or not. + type Extra; + + /// Returns `true` if the thing is opaque, and `false` otherwise. + /// + /// May only be called when `ctx` is in the codegen phase. + fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool; +} + +/// A trait for determining if some IR thing has type parameter in array or not. +pub(crate) trait HasTypeParamInArray { + /// Returns `true` if the thing has Array, and `false` otherwise. + fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool; +} + +/// A trait for iterating over an item and its parents and up its ancestor chain +/// up to (but not including) the implicit root module. +pub(crate) trait ItemAncestors { + /// Get an iterable over this item's ancestors. + fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>; +} + +#[cfg(feature = "__testing_only_extra_assertions")] +type DebugOnlyItemSet = ItemSet; + +#[cfg(not(feature = "__testing_only_extra_assertions"))] +struct DebugOnlyItemSet; + +#[cfg(not(feature = "__testing_only_extra_assertions"))] +impl DebugOnlyItemSet { + fn new() -> Self { + DebugOnlyItemSet + } + + #[allow(clippy::trivially_copy_pass_by_ref)] + fn contains(&self, _id: &ItemId) -> bool { + false + } + + fn insert(&mut self, _id: ItemId) {} +} + +/// An iterator over an item and its ancestors. +pub(crate) struct ItemAncestorsIter<'a> { + item: ItemId, + ctx: &'a BindgenContext, + seen: DebugOnlyItemSet, +} + +impl<'a> ItemAncestorsIter<'a> { + fn new>(ctx: &'a BindgenContext, id: Id) -> Self { + ItemAncestorsIter { + item: id.into(), + ctx, + seen: DebugOnlyItemSet::new(), + } + } +} + +impl Iterator for ItemAncestorsIter<'_> { + type Item = ItemId; + + fn next(&mut self) -> Option { + let item = self.ctx.resolve_item(self.item); + + if item.parent_id() == self.item { + None + } else { + self.item = item.parent_id(); + + extra_assert!(!self.seen.contains(&item.id())); + self.seen.insert(item.id()); + + Some(item.id()) + } + } +} + +impl AsTemplateParam for T +where + T: Copy + Into, +{ + type Extra = (); + + fn as_template_param( + &self, + ctx: &BindgenContext, + _: &(), + ) -> Option { + ctx.resolve_item((*self).into()).as_template_param(ctx, &()) + } +} + +impl AsTemplateParam for Item { + type Extra = (); + + fn as_template_param( + &self, + ctx: &BindgenContext, + _: &(), + ) -> Option { + self.kind.as_template_param(ctx, self) + } +} + +impl AsTemplateParam for ItemKind { + type Extra = Item; + + fn as_template_param( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> Option { + match *self { + ItemKind::Type(ref ty) => ty.as_template_param(ctx, item), + ItemKind::Module(..) | + ItemKind::Function(..) | + ItemKind::Var(..) => None, + } + } +} + +impl ItemCanonicalName for T +where + T: Copy + Into, +{ + fn canonical_name(&self, ctx: &BindgenContext) -> String { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.resolve_item(*self).canonical_name(ctx) + } +} + +impl ItemCanonicalPath for T +where + T: Copy + Into, +{ + fn namespace_aware_canonical_path( + &self, + ctx: &BindgenContext, + ) -> Vec { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.resolve_item(*self).namespace_aware_canonical_path(ctx) + } + + fn canonical_path(&self, ctx: &BindgenContext) -> Vec { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.resolve_item(*self).canonical_path(ctx) + } +} + +impl ItemAncestors for T +where + T: Copy + Into, +{ + fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> { + ItemAncestorsIter::new(ctx, *self) + } +} + +impl ItemAncestors for Item { + fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> { + self.id().ancestors(ctx) + } +} + +impl Trace for Id +where + Id: Copy + Into, +{ + type Extra = (); + + fn trace(&self, ctx: &BindgenContext, tracer: &mut T, extra: &()) + where + T: Tracer, + { + ctx.resolve_item(*self).trace(ctx, tracer, extra); + } +} + +impl Trace for Item { + type Extra = (); + + fn trace(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &()) + where + T: Tracer, + { + // Even if this item is blocklisted/hidden, we want to trace it. It is + // traversal iterators' consumers' responsibility to filter items as + // needed. Generally, this filtering happens in the implementation of + // `Iterator` for `allowlistedItems`. Fully tracing blocklisted items is + // necessary for things like the template parameter usage analysis to + // function correctly. + + match *self.kind() { + ItemKind::Type(ref ty) => { + // There are some types, like resolved type references, where we + // don't want to stop collecting types even though they may be + // opaque. + if ty.should_be_traced_unconditionally() || + !self.is_opaque(ctx, &()) + { + ty.trace(ctx, tracer, self); + } + } + ItemKind::Function(ref fun) => { + // Just the same way, it has not real meaning for a function to + // be opaque, so we trace across it. + tracer.visit(fun.signature().into()); + } + ItemKind::Var(ref var) => { + tracer.visit_kind(var.ty().into(), EdgeKind::VarType); + } + ItemKind::Module(_) => { + // Module -> children edges are "weak", and we do not want to + // trace them. If we did, then allowlisting wouldn't work as + // expected: everything in every module would end up + // allowlisted. + // + // TODO: make a new edge kind for module -> children edges and + // filter them during allowlisting traversals. + } + } + } +} + +impl CanDeriveDebug for Item { + fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_debug(ctx) + } +} + +impl CanDeriveDefault for Item { + fn can_derive_default(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_default(ctx) + } +} + +impl CanDeriveCopy for Item { + fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_copy(ctx) + } +} + +impl CanDeriveHash for Item { + fn can_derive_hash(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_hash(ctx) + } +} + +impl CanDerivePartialOrd for Item { + fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_partialord(ctx) + } +} + +impl CanDerivePartialEq for Item { + fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_partialeq(ctx) + } +} + +impl CanDeriveEq for Item { + fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_eq(ctx) + } +} + +impl CanDeriveOrd for Item { + fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { + self.id().can_derive_ord(ctx) + } +} + +/// An item is the base of the bindgen representation, it can be either a +/// module, a type, a function, or a variable (see `ItemKind` for more +/// information). +/// +/// Items refer to each other by `ItemId`. Every item has its parent's +/// ID. Depending on the kind of item this is, it may also refer to other items, +/// such as a compound type item referring to other types. Collectively, these +/// references form a graph. +/// +/// The entry-point to this graph is the "root module": a meta-item used to hold +/// all top-level items. +/// +/// An item may have a comment, and annotations (see the `annotations` module). +/// +/// Note that even though we parse all the types of annotations in comments, not +/// all of them apply to every item. Those rules are described in the +/// `annotations` module. +#[derive(Debug)] +pub(crate) struct Item { + /// This item's ID. + id: ItemId, + + /// The item's local ID, unique only amongst its siblings. Only used for + /// anonymous items. + /// + /// Lazily initialized in `local_id()`. + /// + /// Note that only structs, unions, and enums get a local type ID. In any + /// case this is an implementation detail. + local_id: OnceCell, + + /// The next local ID to use for a child or template instantiation. + next_child_local_id: Cell, + + /// A cached copy of the canonical name, as returned by `canonical_name`. + /// + /// This is a fairly used operation during codegen so this makes bindgen + /// considerably faster in those cases. + canonical_name: OnceCell, + + /// The path to use for allowlisting and other name-based checks, as + /// returned by `path_for_allowlisting`, lazily constructed. + path_for_allowlisting: OnceCell>, + + /// A doc comment over the item, if any. + comment: Option, + /// Annotations extracted from the doc comment, or the default ones + /// otherwise. + annotations: Annotations, + /// An item's parent ID. This will most likely be a class where this item + /// was declared, or a module, etc. + /// + /// All the items have a parent, except the root module, in which case the + /// parent ID is its own ID. + parent_id: ItemId, + /// The item kind. + kind: ItemKind, + /// The source location of the item. + location: Option, +} + +impl AsRef for Item { + fn as_ref(&self) -> &ItemId { + &self.id + } +} + +impl Item { + /// Construct a new `Item`. + pub(crate) fn new( + id: ItemId, + comment: Option, + annotations: Option, + parent_id: ItemId, + kind: ItemKind, + location: Option, + ) -> Self { + debug_assert!(id != parent_id || kind.is_module()); + Item { + id, + local_id: OnceCell::new(), + next_child_local_id: Cell::new(1), + canonical_name: OnceCell::new(), + path_for_allowlisting: OnceCell::new(), + parent_id, + comment, + annotations: annotations.unwrap_or_default(), + kind, + location, + } + } + + /// Construct a new opaque item type. + pub(crate) fn new_opaque_type( + with_id: ItemId, + ty: &clang::Type, + ctx: &mut BindgenContext, + ) -> TypeId { + let location = ty.declaration().location(); + let ty = Type::new_opaque_from_clang_ty(ty, ctx); + let kind = ItemKind::Type(ty); + let parent = ctx.root_module().into(); + ctx.add_item( + Item::new(with_id, None, None, parent, kind, Some(location)), + None, + None, + ); + with_id.as_type_id_unchecked() + } + + /// Get this `Item`'s identifier. + pub(crate) fn id(&self) -> ItemId { + self.id + } + + /// Get this `Item`'s parent's identifier. + /// + /// For the root module, the parent's ID is its own ID. + pub(crate) fn parent_id(&self) -> ItemId { + self.parent_id + } + + /// Set this item's parent ID. + /// + /// This is only used so replacements get generated in the proper module. + pub(crate) fn set_parent_for_replacement>( + &mut self, + id: Id, + ) { + self.parent_id = id.into(); + } + + /// Returns the depth this item is indented to. + /// + /// FIXME(emilio): This may need fixes for the enums within modules stuff. + pub(crate) fn codegen_depth(&self, ctx: &BindgenContext) -> usize { + if !ctx.options().enable_cxx_namespaces { + return 0; + } + + self.ancestors(ctx) + .filter(|id| { + ctx.resolve_item(*id).as_module().is_some_and(|module| { + !module.is_inline() || + ctx.options().conservative_inline_namespaces + }) + }) + .count() + + 1 + } + + /// Get this `Item`'s comment, if it has any, already preprocessed and with + /// the right indentation. + pub(crate) fn comment(&self, ctx: &BindgenContext) -> Option { + if !ctx.options().generate_comments { + return None; + } + + self.comment + .as_ref() + .map(|comment| ctx.options().process_comment(comment)) + } + + /// What kind of item is this? + pub(crate) fn kind(&self) -> &ItemKind { + &self.kind + } + + /// Get a mutable reference to this item's kind. + pub(crate) fn kind_mut(&mut self) -> &mut ItemKind { + &mut self.kind + } + + /// Where in the source is this item located? + pub(crate) fn location(&self) -> Option<&clang::SourceLocation> { + self.location.as_ref() + } + + /// Get an identifier that differentiates this item from its siblings. + /// + /// This should stay relatively stable in the face of code motion outside or + /// below this item's lexical scope, meaning that this can be useful for + /// generating relatively stable identifiers within a scope. + pub(crate) fn local_id(&self, ctx: &BindgenContext) -> usize { + *self.local_id.get_or_init(|| { + let parent = ctx.resolve_item(self.parent_id); + parent.next_child_local_id() + }) + } + + /// Get an identifier that differentiates a child of this item of other + /// related items. + /// + /// This is currently used for anonymous items, and template instantiation + /// tests, in both cases in order to reduce noise when system headers are at + /// place. + pub(crate) fn next_child_local_id(&self) -> usize { + let local_id = self.next_child_local_id.get(); + self.next_child_local_id.set(local_id + 1); + local_id + } + + /// Returns whether this item is a top-level item, from the point of view of + /// bindgen. + /// + /// This point of view changes depending on whether namespaces are enabled + /// or not. That way, in the following example: + /// + /// ```c++ + /// namespace foo { + /// static int var; + /// } + /// ``` + /// + /// `var` would be a toplevel item if namespaces are disabled, but won't if + /// they aren't. + /// + /// This function is used to determine when the codegen phase should call + /// `codegen` on an item, since any item that is not top-level will be + /// generated by its parent. + pub(crate) fn is_toplevel(&self, ctx: &BindgenContext) -> bool { + // FIXME: Workaround for some types falling behind when parsing weird + // stl classes, for example. + if ctx.options().enable_cxx_namespaces && + self.kind().is_module() && + self.id() != ctx.root_module() + { + return false; + } + + let mut parent = self.parent_id; + loop { + let Some(parent_item) = ctx.resolve_item_fallible(parent) else { + return false; + }; + + if parent_item.id() == ctx.root_module() { + return true; + } else if ctx.options().enable_cxx_namespaces || + !parent_item.kind().is_module() + { + return false; + } + + parent = parent_item.parent_id(); + } + } + + /// Get a reference to this item's underlying `Type`. Panic if this is some + /// other kind of item. + pub(crate) fn expect_type(&self) -> &Type { + self.kind().expect_type() + } + + /// Get a reference to this item's underlying `Type`, or `None` if this is + /// some other kind of item. + pub(crate) fn as_type(&self) -> Option<&Type> { + self.kind().as_type() + } + + /// Get a reference to this item's underlying `Function`. Panic if this is + /// some other kind of item. + pub(crate) fn expect_function(&self) -> &Function { + self.kind().expect_function() + } + + /// Is this item a module? + pub(crate) fn is_module(&self) -> bool { + matches!(self.kind, ItemKind::Module(..)) + } + + /// Get this item's annotations. + pub(crate) fn annotations(&self) -> &Annotations { + &self.annotations + } + + /// Whether this item should be blocklisted. + /// + /// This may be due to either annotations or to other kind of configuration. + pub(crate) fn is_blocklisted(&self, ctx: &BindgenContext) -> bool { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + if self.annotations.hide() { + return true; + } + + if !ctx.options().blocklisted_files.is_empty() { + if let Some(location) = &self.location { + let (file, _, _, _) = location.location(); + if let Some(filename) = file.name() { + if ctx.options().blocklisted_files.matches(filename) { + return true; + } + } + } + } + + let path = self.path_for_allowlisting(ctx); + let name = path[1..].join("::"); + ctx.options().blocklisted_items.matches(&name) || + match self.kind { + ItemKind::Type(..) => { + ctx.options().blocklisted_types.matches(&name) || + ctx.is_replaced_type(path, self.id) + } + ItemKind::Function(..) => { + ctx.options().blocklisted_functions.matches(&name) + } + ItemKind::Var(..) => { + ctx.options().blocklisted_vars.matches(&name) + } + // TODO: Add namespace blocklisting? + ItemKind::Module(..) => false, + } + } + + /// Take out item `NameOptions` + pub(crate) fn name<'a>( + &'a self, + ctx: &'a BindgenContext, + ) -> NameOptions<'a> { + NameOptions::new(self, ctx) + } + + /// Get the target item ID for name generation. + fn name_target(&self, ctx: &BindgenContext) -> ItemId { + let mut targets_seen = DebugOnlyItemSet::new(); + let mut item = self; + + loop { + extra_assert!(!targets_seen.contains(&item.id())); + targets_seen.insert(item.id()); + + if self.annotations().use_instead_of().is_some() { + return self.id(); + } + + match *item.kind() { + ItemKind::Type(ref ty) => match *ty.kind() { + TypeKind::ResolvedTypeRef(inner) => { + item = ctx.resolve_item(inner); + } + TypeKind::TemplateInstantiation(ref inst) => { + item = ctx.resolve_item(inst.template_definition()); + } + _ => return item.id(), + }, + _ => return item.id(), + } + } + } + + /// Create a fully disambiguated name for an item, including template + /// parameters if it is a type + pub(crate) fn full_disambiguated_name( + &self, + ctx: &BindgenContext, + ) -> String { + let mut s = String::new(); + let level = 0; + self.push_disambiguated_name(ctx, &mut s, level); + s + } + + /// Helper function for `full_disambiguated_name` + fn push_disambiguated_name( + &self, + ctx: &BindgenContext, + to: &mut String, + level: u8, + ) { + to.push_str(&self.canonical_name(ctx)); + if let ItemKind::Type(ref ty) = *self.kind() { + if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() { + let _ = write!(to, "_open{level}_"); + for arg in inst.template_arguments() { + arg.into_resolver() + .through_type_refs() + .resolve(ctx) + .push_disambiguated_name(ctx, to, level + 1); + to.push('_'); + } + let _ = write!(to, "close{level}"); + } + } + } + + /// Get this function item's name, or `None` if this item is not a function. + fn func_name(&self) -> Option<&str> { + match *self.kind() { + ItemKind::Function(ref func) => Some(func.name()), + _ => None, + } + } + + /// Get the overload index for this method. If this is not a method, return + /// `None`. + fn overload_index(&self, ctx: &BindgenContext) -> Option { + self.func_name().and_then(|func_name| { + let parent = ctx.resolve_item(self.parent_id()); + if let ItemKind::Type(ref ty) = *parent.kind() { + if let TypeKind::Comp(ref ci) = *ty.kind() { + // All the constructors have the same name, so no need to + // resolve and check. + return ci + .constructors() + .iter() + .position(|c| *c == self.id()) + .or_else(|| { + ci.methods() + .iter() + .filter(|m| { + let item = ctx.resolve_item(m.signature()); + let func = item.expect_function(); + func.name() == func_name + }) + .position(|m| m.signature() == self.id()) + }); + } + } + + None + }) + } + + /// Get this item's base name (aka non-namespaced name). + fn base_name(&self, ctx: &BindgenContext) -> String { + if let Some(path) = self.annotations().use_instead_of() { + return path.last().unwrap().clone(); + } + + match *self.kind() { + ItemKind::Var(ref var) => var.name().to_owned(), + ItemKind::Module(ref module) => module.name().map_or_else( + || format!("_bindgen_mod_{}", self.exposed_id(ctx)), + ToOwned::to_owned, + ), + ItemKind::Type(ref ty) => ty.sanitized_name(ctx).map_or_else( + || format!("_bindgen_ty_{}", self.exposed_id(ctx)), + Into::into, + ), + ItemKind::Function(ref fun) => { + let mut name = fun.name().to_owned(); + + if let Some(idx) = self.overload_index(ctx) { + if idx > 0 { + write!(&mut name, "{idx}").unwrap(); + } + } + + name + } + } + } + + fn is_anon(&self) -> bool { + match self.kind() { + ItemKind::Module(module) => module.name().is_none(), + ItemKind::Type(ty) => ty.name().is_none(), + ItemKind::Function(_) => false, + ItemKind::Var(_) => false, + } + } + + /// Get the canonical name without taking into account the replaces + /// annotation. + /// + /// This is the base logic used to implement hiding and replacing via + /// annotations, and also to implement proper name mangling. + /// + /// The idea is that each generated type in the same "level" (read: module + /// or namespace) has a unique canonical name. + /// + /// This name should be derived from the immutable state contained in the + /// type and the parent chain, since it should be consistent. + /// + /// If `BindgenOptions::disable_nested_struct_naming` is true then returned + /// name is the inner most non-anonymous name plus all the anonymous base names + /// that follows. + pub(crate) fn real_canonical_name( + &self, + ctx: &BindgenContext, + opt: &NameOptions, + ) -> String { + let target = ctx.resolve_item(self.name_target(ctx)); + + // Short-circuit if the target has an override, and just use that. + if let Some(path) = target.annotations.use_instead_of() { + if ctx.options().enable_cxx_namespaces { + return path.last().unwrap().clone(); + } + return path.join("_"); + } + + let base_name = target.base_name(ctx); + + // Named template type arguments are never namespaced, and never + // mangled. + if target.is_template_param(ctx, &()) { + return base_name; + } + + // Ancestors' ID iter + let mut ids_iter = target + .parent_id() + .ancestors(ctx) + .filter(|id| *id != ctx.root_module()) + .take_while(|id| { + // Stop iterating ancestors once we reach a non-inline namespace + // when opt.within_namespaces is set. + !opt.within_namespaces || !ctx.resolve_item(*id).is_module() + }) + .filter(|id| { + if !ctx.options().conservative_inline_namespaces { + if let ItemKind::Module(ref module) = + *ctx.resolve_item(*id).kind() + { + return !module.is_inline(); + } + } + + true + }); + + let ids: Vec<_> = if ctx.options().disable_nested_struct_naming { + let mut ids = Vec::new(); + + // If target is anonymous we need find its first named ancestor. + if target.is_anon() { + for id in ids_iter.by_ref() { + ids.push(id); + + if !ctx.resolve_item(id).is_anon() { + break; + } + } + } + + ids + } else { + ids_iter.collect() + }; + + // Concatenate this item's ancestors' names together. + let mut names: Vec<_> = ids + .into_iter() + .map(|id| { + let item = ctx.resolve_item(id); + let target = ctx.resolve_item(item.name_target(ctx)); + target.base_name(ctx) + }) + .filter(|name| !name.is_empty()) + .collect(); + + names.reverse(); + + if !base_name.is_empty() { + names.push(base_name); + } + + if ctx.options().c_naming { + if let Some(prefix) = self.c_naming_prefix() { + names.insert(0, prefix.to_string()); + } + } + + let name = names.join("_"); + + let name = if opt.user_mangled == UserMangled::Yes { + let item_info = ItemInfo { + name: &name, + kind: match self.kind() { + ItemKind::Module(..) => crate::callbacks::ItemKind::Module, + ItemKind::Type(..) => crate::callbacks::ItemKind::Type, + ItemKind::Function(..) => { + crate::callbacks::ItemKind::Function + } + ItemKind::Var(..) => crate::callbacks::ItemKind::Var, + }, + }; + ctx.options() + .last_callback(|callbacks| callbacks.item_name(item_info)) + .unwrap_or(name) + } else { + name + }; + + ctx.rust_mangle(&name).into_owned() + } + + /// The exposed ID that represents an unique ID among the siblings of a + /// given item. + pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String { + // Only use local ids for enums, classes, structs and union types. All + // other items use their global ID. + let ty_kind = self.kind().as_type().map(|t| t.kind()); + if let Some( + TypeKind::Comp(..) | + TypeKind::TemplateInstantiation(..) | + TypeKind::Enum(..), + ) = ty_kind + { + return self.local_id(ctx).to_string(); + } + + // Note that this `id_` prefix prevents (really unlikely) collisions + // between the global ID and the local ID of an item with the same + // parent. + format!("id_{}", self.id().as_usize()) + } + + /// Get a reference to this item's `Module`, or `None` if this is not a + /// `Module` item. + pub(crate) fn as_module(&self) -> Option<&Module> { + match self.kind { + ItemKind::Module(ref module) => Some(module), + _ => None, + } + } + + /// Get a mutable reference to this item's `Module`, or `None` if this is + /// not a `Module` item. + pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> { + match self.kind { + ItemKind::Module(ref mut module) => Some(module), + _ => None, + } + } + + /// Returns whether the item is a constified module enum + fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool { + // Do not jump through aliases, except for aliases that point to a type + // with the same name, since we dont generate coe for them. + let item = self.id.into_resolver().through_type_refs().resolve(ctx); + let ItemKind::Type(ref type_) = *item.kind() else { + return false; + }; + + match *type_.kind() { + TypeKind::Enum(ref enum_) => { + enum_.computed_enum_variation(ctx, self) == + EnumVariation::ModuleConsts + } + TypeKind::Alias(inner_id) => { + // TODO(emilio): Make this "hop through type aliases that aren't + // really generated" an option in `ItemResolver`? + let inner_item = ctx.resolve_item(inner_id); + let name = item.canonical_name(ctx); + + if inner_item.canonical_name(ctx) == name { + inner_item.is_constified_enum_module(ctx) + } else { + false + } + } + _ => false, + } + } + + /// Is this item of a kind that is enabled for code generation? + pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool { + let cc = &ctx.options().codegen_config; + match *self.kind() { + ItemKind::Module(..) => true, + ItemKind::Var(_) => cc.vars(), + ItemKind::Type(_) => cc.types(), + ItemKind::Function(ref f) => match f.kind() { + FunctionKind::Function => cc.functions(), + FunctionKind::Method(MethodKind::Constructor) => { + cc.constructors() + } + FunctionKind::Method( + MethodKind::Destructor | + MethodKind::VirtualDestructor { .. }, + ) => cc.destructors(), + FunctionKind::Method( + MethodKind::Static | + MethodKind::Normal | + MethodKind::Virtual { .. }, + ) => cc.methods(), + }, + } + } + + /// Returns the path we should use for allowlisting / blocklisting, which + /// doesn't include user-mangling. + pub(crate) fn path_for_allowlisting( + &self, + ctx: &BindgenContext, + ) -> &Vec { + self.path_for_allowlisting + .get_or_init(|| self.compute_path(ctx, UserMangled::No)) + } + + fn compute_path( + &self, + ctx: &BindgenContext, + mangled: UserMangled, + ) -> Vec { + if let Some(path) = self.annotations().use_instead_of() { + let mut ret = + vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()]; + ret.extend_from_slice(path); + return ret; + } + + let target = ctx.resolve_item(self.name_target(ctx)); + let mut path: Vec<_> = target + .ancestors(ctx) + .chain(iter::once(ctx.root_module().into())) + .map(|id| ctx.resolve_item(id)) + .filter(|item| { + item.id() == target.id() || + item.as_module().is_some_and(|module| { + !module.is_inline() || + ctx.options().conservative_inline_namespaces + }) + }) + .map(|item| { + ctx.resolve_item(item.name_target(ctx)) + .name(ctx) + .within_namespaces() + .user_mangled(mangled) + .get() + }) + .collect(); + path.reverse(); + path + } + + /// Returns a prefix for the canonical name when C naming is enabled. + fn c_naming_prefix(&self) -> Option<&str> { + let ItemKind::Type(ref ty) = self.kind else { + return None; + }; + + Some(match ty.kind() { + TypeKind::Comp(ref ci) => match ci.kind() { + CompKind::Struct => "struct", + CompKind::Union => "union", + }, + TypeKind::Enum(..) => "enum", + _ => return None, + }) + } + + /// Whether this is a `#[must_use]` type. + pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool { + self.annotations().must_use_type() || ctx.must_use_type_by_name(self) + } + + /// Get the alias style for this item. + pub(crate) fn alias_style(&self, ctx: &BindgenContext) -> AliasVariation { + let name = self.canonical_name(ctx); + if ctx.options().type_alias.matches(&name) { + AliasVariation::TypeAlias + } else if ctx.options().new_type_alias.matches(&name) { + AliasVariation::NewType + } else if ctx.options().new_type_alias_deref.matches(&name) { + AliasVariation::NewTypeDeref + } else { + ctx.options().default_alias_style + } + } +} + +impl IsOpaque for T +where + T: Copy + Into, +{ + type Extra = (); + + fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.resolve_item((*self).into()).is_opaque(ctx, &()) + } +} + +impl IsOpaque for Item { + type Extra = (); + + fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + self.annotations.opaque() || + self.as_type().is_some_and(|ty| ty.is_opaque(ctx, self)) || + ctx.opaque_by_name(self.path_for_allowlisting(ctx)) + } +} + +impl HasVtable for T +where + T: Copy + Into, +{ + fn has_vtable(&self, ctx: &BindgenContext) -> bool { + let id: ItemId = (*self).into(); + id.as_type_id(ctx).is_some_and(|id| { + !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No) + }) + } + + fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool { + let id: ItemId = (*self).into(); + id.as_type_id(ctx).is_some_and(|id| { + matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable) + }) + } +} + +impl HasVtable for Item { + fn has_vtable(&self, ctx: &BindgenContext) -> bool { + self.id().has_vtable(ctx) + } + + fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool { + self.id().has_vtable_ptr(ctx) + } +} + +impl Sizedness for T +where + T: Copy + Into, +{ + fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult { + let id: ItemId = (*self).into(); + id.as_type_id(ctx) + .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id)) + } +} + +impl Sizedness for Item { + fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult { + self.id().sizedness(ctx) + } +} + +impl HasTypeParamInArray for T +where + T: Copy + Into, +{ + fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.lookup_has_type_param_in_array(*self) + } +} + +impl HasTypeParamInArray for Item { + fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + ctx.lookup_has_type_param_in_array(self.id()) + } +} + +/// A set of items. +pub(crate) type ItemSet = BTreeSet; + +impl DotAttributes for Item { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!( + out, + "{:?} + name{}", + self.id, + self.name(ctx).get() + )?; + + if self.is_opaque(ctx, &()) { + writeln!(out, "opaquetrue")?; + } + + self.kind.dot_attributes(ctx, out) + } +} + +impl TemplateParameters for T +where + T: Copy + Into, +{ + fn self_template_params(&self, ctx: &BindgenContext) -> Vec { + ctx.resolve_item_fallible(*self) + .map_or(vec![], |item| item.self_template_params(ctx)) + } +} + +impl TemplateParameters for Item { + fn self_template_params(&self, ctx: &BindgenContext) -> Vec { + self.kind.self_template_params(ctx) + } +} + +impl TemplateParameters for ItemKind { + fn self_template_params(&self, ctx: &BindgenContext) -> Vec { + match *self { + ItemKind::Type(ref ty) => ty.self_template_params(ctx), + // If we start emitting bindings to explicitly instantiated + // functions, then we'll need to check ItemKind::Function for + // template params. + ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => { + vec![] + } + } + } +} + +// An utility function to handle recursing inside nested types. +fn visit_child( + cur: clang::Cursor, + id: ItemId, + ty: &clang::Type, + parent_id: Option, + ctx: &mut BindgenContext, + result: &mut Result, +) -> clang_sys::CXChildVisitResult { + use clang_sys::*; + if result.is_ok() { + return CXChildVisit_Break; + } + + *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx); + + match *result { + Ok(..) => CXChildVisit_Break, + Err(ParseError::Recurse) => { + cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result)); + CXChildVisit_Continue + } + Err(ParseError::Continue) => CXChildVisit_Continue, + } +} + +impl Item { + /// Create a builtin type. + pub(crate) fn builtin_type( + kind: TypeKind, + is_const: bool, + ctx: &mut BindgenContext, + ) -> TypeId { + // Feel free to add more here, I'm just lazy. + match kind { + TypeKind::Void | + TypeKind::Int(..) | + TypeKind::Pointer(..) | + TypeKind::Float(..) => {} + _ => panic!("Unsupported builtin type"), + } + + let ty = Type::new(None, None, kind, is_const); + let id = ctx.next_item_id(); + let module = ctx.root_module().into(); + ctx.add_item( + Item::new(id, None, None, module, ItemKind::Type(ty), None), + None, + None, + ); + id.as_type_id_unchecked() + } + + /// Parse this item from the given Clang cursor. + pub(crate) fn parse( + cursor: clang::Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> Result { + use crate::ir::var::Var; + use clang_sys::*; + + if !cursor.is_valid() { + return Err(ParseError::Continue); + } + + let comment = cursor.raw_comment(); + let annotations = Annotations::new(&cursor); + + let current_module = ctx.current_module().into(); + let relevant_parent_id = parent_id.unwrap_or(current_module); + + #[allow(clippy::missing_docs_in_private_items)] + macro_rules! try_parse { + ($what:ident) => { + match $what::parse(cursor, ctx) { + Ok(ParseResult::New(item, declaration)) => { + let id = ctx.next_item_id(); + + ctx.add_item( + Item::new( + id, + comment, + annotations, + relevant_parent_id, + ItemKind::$what(item), + Some(cursor.location()), + ), + declaration, + Some(cursor), + ); + return Ok(id); + } + Ok(ParseResult::AlreadyResolved(id)) => { + return Ok(id); + } + Err(ParseError::Recurse) => return Err(ParseError::Recurse), + Err(ParseError::Continue) => {} + } + }; + } + + try_parse!(Module); + + // NOTE: Is extremely important to parse functions and vars **before** + // types. Otherwise we can parse a function declaration as a type + // (which is legal), and lose functions to generate. + // + // In general, I'm not totally confident this split between + // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but + // I guess we can try. + try_parse!(Function); + try_parse!(Var); + + // Types are sort of special, so to avoid parsing template classes + // twice, handle them separately. + { + let definition = cursor.definition(); + let applicable_cursor = definition.unwrap_or(cursor); + + let relevant_parent_id = match definition { + Some(definition) => { + if definition != cursor { + ctx.add_semantic_parent(definition, relevant_parent_id); + return Ok(Item::from_ty_or_ref( + applicable_cursor.cur_type(), + cursor, + parent_id, + ctx, + ) + .into()); + } + ctx.known_semantic_parent(definition) + .or(parent_id) + .unwrap_or_else(|| ctx.current_module().into()) + } + None => relevant_parent_id, + }; + + match Item::from_ty( + &applicable_cursor.cur_type(), + applicable_cursor, + Some(relevant_parent_id), + ctx, + ) { + Ok(ty) => return Ok(ty.into()), + Err(ParseError::Recurse) => return Err(ParseError::Recurse), + Err(ParseError::Continue) => {} + } + } + + match cursor.kind() { + // On Clang 18+, extern "C" is reported accurately as a LinkageSpec. + // Older LLVM treat it as UnexposedDecl. + CXCursor_LinkageSpec | CXCursor_UnexposedDecl => { + Err(ParseError::Recurse) + } + + // We allowlist cursors here known to be unhandled, to prevent being + // too noisy about this. + CXCursor_MacroDefinition | + CXCursor_MacroExpansion | + CXCursor_UsingDeclaration | + CXCursor_UsingDirective | + CXCursor_StaticAssert | + CXCursor_FunctionTemplate => { + debug!("Unhandled cursor kind {:?}: {cursor:?}", cursor.kind()); + Err(ParseError::Continue) + } + + CXCursor_InclusionDirective => { + let file = cursor.get_included_file_name(); + match file { + None => { + warn!("Inclusion of a nameless file in {cursor:?}"); + } + Some(included_file) => { + for cb in &ctx.options().parse_callbacks { + cb.include_file(&included_file); + } + + ctx.add_dep(included_file.into_boxed_str()); + } + } + Err(ParseError::Continue) + } + + _ => { + // ignore toplevel operator overloads + let spelling = cursor.spelling(); + if !spelling.starts_with("operator") { + warn!( + "Unhandled cursor kind {:?}: {cursor:?}", + cursor.kind(), + ); + } + Err(ParseError::Continue) + } + } + } + + /// Parse this item from the given Clang type, or if we haven't resolved all + /// the other items this one depends on, an unresolved reference. + pub(crate) fn from_ty_or_ref( + ty: clang::Type, + location: clang::Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> TypeId { + let id = ctx.next_item_id(); + Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx) + } + + /// Parse a C++ type. If we find a reference to a type that has not been + /// defined yet, use `UnresolvedTypeRef` as a placeholder. + /// + /// This logic is needed to avoid parsing items with the incorrect parent + /// and it's sort of complex to explain, so I'll just point to + /// `tests/headers/typeref.hpp` to see the kind of constructs that forced + /// this. + /// + /// Typerefs are resolved once parsing is completely done, see + /// `BindgenContext::resolve_typerefs`. + pub(crate) fn from_ty_or_ref_with_id( + potential_id: ItemId, + ty: clang::Type, + location: clang::Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> TypeId { + debug!("from_ty_or_ref_with_id: {potential_id:?} {ty:?}, {location:?}, {parent_id:?}"); + + if ctx.collected_typerefs() { + debug!("refs already collected, resolving directly"); + return Item::from_ty_with_id( + potential_id, + &ty, + location, + parent_id, + ctx, + ) + .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx)); + } + + if let Some(ty) = ctx.builtin_or_resolved_ty( + potential_id, + parent_id, + &ty, + Some(location), + ) { + debug!("{ty:?} already resolved: {location:?}"); + return ty; + } + + debug!("New unresolved type reference: {ty:?}, {location:?}"); + + let is_const = ty.is_const(); + let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id); + let current_module = ctx.current_module(); + + ctx.add_item( + Item::new( + potential_id, + None, + None, + parent_id.unwrap_or_else(|| current_module.into()), + ItemKind::Type(Type::new(None, None, kind, is_const)), + Some(location.location()), + ), + None, + None, + ); + potential_id.as_type_id_unchecked() + } + + /// Parse this item from the given Clang type. See [`Item::from_ty_with_id`]. + pub(crate) fn from_ty( + ty: &clang::Type, + location: clang::Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> Result { + let id = ctx.next_item_id(); + Item::from_ty_with_id(id, ty, location, parent_id, ctx) + } + + /// This is one of the trickiest methods you'll find (probably along with + /// some of the ones that handle templates in `BindgenContext`). + /// + /// This method parses a type, given the potential ID of that type (if + /// parsing it was correct), an optional location we're scanning, which is + /// critical some times to obtain information, an optional parent item ID, + /// that will, if it's `None`, become the current module ID, and the + /// context. + pub(crate) fn from_ty_with_id( + id: ItemId, + ty: &clang::Type, + location: clang::Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> Result { + use clang_sys::*; + + debug!( + "Item::from_ty_with_id: {id:?}\n\ + \tty = {ty:?},\n\ + \tlocation = {location:?}", + ); + + if ty.kind() == CXType_Unexposed || + location.cur_type().kind() == CXType_Unexposed + { + if ty.is_associated_type() || + location.cur_type().is_associated_type() + { + return Ok(Item::new_opaque_type(id, ty, ctx)); + } + + if let Some(param_id) = Item::type_param(None, location, ctx) { + return Ok(ctx.build_ty_wrapper(id, param_id, None, ty)); + } + } + + // Treat all types that are declared inside functions as opaque. The Rust binding + // won't be able to do anything with them anyway. + // + // (If we don't do this check here, we can have subtle logic bugs because we generally + // ignore function bodies. See issue #2036.) + if let Some(ref parent) = ty.declaration().fallible_semantic_parent() { + if FunctionKind::from_cursor(parent).is_some() { + debug!("Skipping type declared inside function: {ty:?}"); + return Ok(Item::new_opaque_type(id, ty, ctx)); + } + } + + let decl = { + let canonical_def = ty.canonical_type().declaration().definition(); + canonical_def.unwrap_or_else(|| ty.declaration()) + }; + + let comment = location.raw_comment().or_else(|| decl.raw_comment()); + + let annotations = + Annotations::new(&decl).or_else(|| Annotations::new(&location)); + + if let Some(ref annotations) = annotations { + if let Some(replaced) = annotations.use_instead_of() { + ctx.replace(replaced, id); + } + } + + if let Some(ty) = + ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location)) + { + return Ok(ty); + } + + // First, check we're not recursing. + let mut valid_decl = decl.kind() != CXCursor_NoDeclFound; + let declaration_to_look_for = if valid_decl { + decl.canonical() + } else if location.kind() == CXCursor_ClassTemplate { + valid_decl = true; + location + } else { + decl + }; + + if valid_decl { + if let Some(partial) = ctx + .currently_parsed_types() + .iter() + .find(|ty| *ty.decl() == declaration_to_look_for) + { + debug!("Avoiding recursion parsing type: {ty:?}"); + // Unchecked because we haven't finished this type yet. + return Ok(partial.id().as_type_id_unchecked()); + } + } + + let current_module = ctx.current_module().into(); + let partial_ty = PartialType::new(declaration_to_look_for, id); + if valid_decl { + ctx.begin_parsing(partial_ty); + } + + let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); + let relevant_parent_id = parent_id.unwrap_or(current_module); + let ret = match result { + Ok(ParseResult::AlreadyResolved(ty)) => { + Ok(ty.as_type_id_unchecked()) + } + Ok(ParseResult::New(item, declaration)) => { + ctx.add_item( + Item::new( + id, + comment, + annotations, + relevant_parent_id, + ItemKind::Type(item), + Some(location.location()), + ), + declaration, + Some(location), + ); + Ok(id.as_type_id_unchecked()) + } + Err(ParseError::Continue) => Err(ParseError::Continue), + Err(ParseError::Recurse) => { + debug!("Item::from_ty recursing in the ast"); + let mut result = Err(ParseError::Recurse); + + // Need to pop here, otherwise we'll get stuck. + // + // TODO: Find a nicer interface, really. Also, the + // declaration_to_look_for suspiciously shares a lot of + // logic with ir::context, so we should refactor that. + if valid_decl { + let finished = ctx.finish_parsing(); + assert_eq!(*finished.decl(), declaration_to_look_for); + } + + location.visit(|cur| { + visit_child(cur, id, ty, parent_id, ctx, &mut result) + }); + + if valid_decl { + let partial_ty = + PartialType::new(declaration_to_look_for, id); + ctx.begin_parsing(partial_ty); + } + + // If we have recursed into the AST all we know, and we still + // haven't found what we've got, let's just try and make a named + // type. + // + // This is what happens with some template members, for example. + if let Err(ParseError::Recurse) = result { + warn!( + "Unknown type, assuming named template type: \ + id = {id:?}; spelling = {}", + ty.spelling() + ); + Item::type_param(Some(id), location, ctx) + .ok_or(ParseError::Recurse) + } else { + result + } + } + }; + + if valid_decl { + let partial_ty = ctx.finish_parsing(); + assert_eq!(*partial_ty.decl(), declaration_to_look_for); + } + + ret + } + + /// A named type is a template parameter, e.g., the `T` in `Foo`. They're always local so + /// it's the only exception when there's no declaration for a type. + pub(crate) fn type_param( + with_id: Option, + location: clang::Cursor, + ctx: &mut BindgenContext, + ) -> Option { + let ty = location.cur_type(); + + debug!( + "Item::type_param:\n\ + \twith_id = {with_id:?},\n\ + \tty = {} {ty:?},\n\ + \tlocation: {location:?}", + ty.spelling(), + ); + + if ty.kind() != clang_sys::CXType_Unexposed { + // If the given cursor's type's kind is not Unexposed, then we + // aren't looking at a template parameter. This check may need to be + // updated in the future if they start properly exposing template + // type parameters. + return None; + } + + let ty_spelling = ty.spelling(); + + // Clang does not expose any information about template type parameters + // via their clang::Type, nor does it give us their canonical cursors + // the straightforward way. However, there are three situations from + // which we can find the definition of the template type parameter, if + // the cursor is indeed looking at some kind of a template type + // parameter or use of one: + // + // 1. The cursor is pointing at the template type parameter's + // definition. This is the trivial case. + // + // (kind = TemplateTypeParameter, ...) + // + // 2. The cursor is pointing at a TypeRef whose referenced() cursor is + // situation (1). + // + // (kind = TypeRef, + // referenced = (kind = TemplateTypeParameter, ...), + // ...) + // + // 3. The cursor is pointing at some use of a template type parameter + // (for example, in a FieldDecl), and this cursor has a child cursor + // whose spelling is the same as the parent's type's spelling, and whose + // kind is a TypeRef of the situation (2) variety. + // + // (kind = FieldDecl, + // type = (kind = Unexposed, + // spelling = "T", + // ...), + // children = + // (kind = TypeRef, + // spelling = "T", + // referenced = (kind = TemplateTypeParameter, + // spelling = "T", + // ...), + // ...) + // ...) + // + // TODO: The alternative to this hacky pattern matching would be to + // maintain proper scopes of template parameters while parsing and use + // de Brujin indices to access template parameters, which clang exposes + // in the cursor's type's canonical type's spelling: + // "type-parameter-x-y". That is probably a better approach long-term, + // but maintaining these scopes properly would require more changes to + // the whole libclang -> IR parsing code. + + fn is_template_with_spelling( + refd: &clang::Cursor, + spelling: &str, + ) -> bool { + static ANON_TYPE_PARAM_RE: OnceLock = OnceLock::new(); + let anon_type_param_re = ANON_TYPE_PARAM_RE.get_or_init(|| { + regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap() + }); + + if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter { + return false; + } + + let refd_spelling = refd.spelling(); + refd_spelling == spelling || + // Allow for anonymous template parameters. + (refd_spelling.is_empty() && anon_type_param_re.is_match(spelling.as_ref())) + } + + let definition = if is_template_with_spelling(&location, &ty_spelling) { + // Situation (1) + location + } else if location.kind() == clang_sys::CXCursor_TypeRef { + // Situation (2) + match location.referenced() { + Some(refd) + if is_template_with_spelling(&refd, &ty_spelling) => + { + refd + } + _ => return None, + } + } else { + // Situation (3) + let mut definition = None; + + location.visit(|child| { + let child_ty = child.cur_type(); + if child_ty.kind() == clang_sys::CXCursor_TypeRef && + child_ty.spelling() == ty_spelling + { + match child.referenced() { + Some(refd) + if is_template_with_spelling( + &refd, + &ty_spelling, + ) => + { + definition = Some(refd); + return clang_sys::CXChildVisit_Break; + } + _ => {} + } + } + + clang_sys::CXChildVisit_Continue + }); + + definition? + }; + assert!(is_template_with_spelling(&definition, &ty_spelling)); + + // Named types are always parented to the root module. They are never + // referenced with namespace prefixes, and they can't inherit anything + // from their parent either, so it is simplest to just hang them off + // something we know will always exist. + let parent = ctx.root_module().into(); + + if let Some(id) = ctx.get_type_param(&definition) { + return Some(if let Some(with_id) = with_id { + ctx.build_ty_wrapper(with_id, id, Some(parent), &ty) + } else { + id + }); + } + + // See tests/headers/const_tparam.hpp and + // tests/headers/variadic_tname.hpp. + let name = ty_spelling.replace("const ", "").replace('.', ""); + + let id = with_id.unwrap_or_else(|| ctx.next_item_id()); + let item = Item::new( + id, + None, + None, + parent, + ItemKind::Type(Type::named(name)), + Some(location.location()), + ); + ctx.add_type_param(item, definition); + Some(id.as_type_id_unchecked()) + } +} + +impl ItemCanonicalName for Item { + fn canonical_name(&self, ctx: &BindgenContext) -> String { + debug_assert!( + ctx.in_codegen_phase(), + "You're not supposed to call this yet" + ); + self.canonical_name + .get_or_init(|| { + let in_namespace = ctx.options().enable_cxx_namespaces || + ctx.options().disable_name_namespacing; + + if in_namespace { + self.name(ctx).within_namespaces().get() + } else { + self.name(ctx).get() + } + }) + .clone() + } +} + +impl ItemCanonicalPath for Item { + fn namespace_aware_canonical_path( + &self, + ctx: &BindgenContext, + ) -> Vec { + let mut path = self.canonical_path(ctx); + + // ASSUMPTION: (disable_name_namespacing && cxx_namespaces) + // is equivalent to + // disable_name_namespacing + if ctx.options().disable_name_namespacing { + // Only keep the last item in path + let split_idx = path.len() - 1; + path = path.split_off(split_idx); + } else if !ctx.options().enable_cxx_namespaces { + // Ignore first item "root" + path = vec![path[1..].join("_")]; + } + + if self.is_constified_enum_module(ctx) { + path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into()); + } + + path + } + + fn canonical_path(&self, ctx: &BindgenContext) -> Vec { + self.compute_path(ctx, UserMangled::Yes) + } +} + +/// Whether to use the user-mangled name (mangled by the `item_name` callback or +/// not. +/// +/// Most of the callers probably want just yes, but the ones dealing with +/// allowlisting and blocklisting don't. +#[derive(Copy, Clone, Debug, PartialEq)] +enum UserMangled { + No, + Yes, +} + +/// Builder struct for naming variations, which hold inside different +/// flags for naming options. +#[derive(Debug)] +pub(crate) struct NameOptions<'a> { + item: &'a Item, + ctx: &'a BindgenContext, + within_namespaces: bool, + user_mangled: UserMangled, +} + +impl<'a> NameOptions<'a> { + /// Construct a new `NameOptions` + pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self { + NameOptions { + item, + ctx, + within_namespaces: false, + user_mangled: UserMangled::Yes, + } + } + + /// Construct the name without the item's containing C++ namespaces mangled + /// into it. In other words, the item's name within the item's namespace. + pub(crate) fn within_namespaces(&mut self) -> &mut Self { + self.within_namespaces = true; + self + } + + fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self { + self.user_mangled = user_mangled; + self + } + + /// Construct a name `String` + pub(crate) fn get(&self) -> String { + self.item.real_canonical_name(self.ctx, self) + } +} diff --git a/bindgen/ir/item_kind.rs b/bindgen/ir/item_kind.rs new file mode 100644 index 0000000000..9221b50579 --- /dev/null +++ b/bindgen/ir/item_kind.rs @@ -0,0 +1,135 @@ +//! Different variants of an `Item` in our intermediate representation. + +use super::context::BindgenContext; +use super::dot::DotAttributes; +use super::function::Function; +use super::module::Module; +use super::ty::Type; +use super::var::Var; +use std::io; + +/// A item we parse and translate. +#[derive(Debug)] +pub(crate) enum ItemKind { + /// A module, created implicitly once (the root module), or via C++ + /// namespaces. + Module(Module), + + /// A type declared in any of the multiple ways it can be declared. + Type(Type), + + /// A function or method declaration. + Function(Function), + + /// A variable declaration, most likely a static. + Var(Var), +} + +impl ItemKind { + /// Get a reference to this `ItemKind`'s underlying `Module`, or `None` if it + /// is some other kind. + pub(crate) fn as_module(&self) -> Option<&Module> { + match *self { + ItemKind::Module(ref module) => Some(module), + _ => None, + } + } + + /// Transform our `ItemKind` into a string. + pub(crate) fn kind_name(&self) -> &'static str { + match *self { + ItemKind::Module(..) => "Module", + ItemKind::Type(..) => "Type", + ItemKind::Function(..) => "Function", + ItemKind::Var(..) => "Var", + } + } + + /// Is this a module? + pub(crate) fn is_module(&self) -> bool { + self.as_module().is_some() + } + + /// Get a reference to this `ItemKind`'s underlying `Function`, or `None` if + /// it is some other kind. + pub(crate) fn as_function(&self) -> Option<&Function> { + match *self { + ItemKind::Function(ref func) => Some(func), + _ => None, + } + } + + /// Is this a function? + pub(crate) fn is_function(&self) -> bool { + self.as_function().is_some() + } + + /// Get a reference to this `ItemKind`'s underlying `Function`, or panic if + /// it is some other kind. + pub(crate) fn expect_function(&self) -> &Function { + self.as_function().expect("Not a function") + } + + /// Get a reference to this `ItemKind`'s underlying `Type`, or `None` if + /// it is some other kind. + pub(crate) fn as_type(&self) -> Option<&Type> { + match *self { + ItemKind::Type(ref ty) => Some(ty), + _ => None, + } + } + + /// Get a mutable reference to this `ItemKind`'s underlying `Type`, or `None` + /// if it is some other kind. + pub(crate) fn as_type_mut(&mut self) -> Option<&mut Type> { + match *self { + ItemKind::Type(ref mut ty) => Some(ty), + _ => None, + } + } + + /// Is this a type? + pub(crate) fn is_type(&self) -> bool { + self.as_type().is_some() + } + + /// Get a reference to this `ItemKind`'s underlying `Type`, or panic if it is + /// some other kind. + pub(crate) fn expect_type(&self) -> &Type { + self.as_type().expect("Not a type") + } + + /// Get a reference to this `ItemKind`'s underlying `Var`, or `None` if it is + /// some other kind. + pub(crate) fn as_var(&self) -> Option<&Var> { + match *self { + ItemKind::Var(ref v) => Some(v), + _ => None, + } + } + + /// Is this a variable? + pub(crate) fn is_var(&self) -> bool { + self.as_var().is_some() + } +} + +impl DotAttributes for ItemKind { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!(out, "kind{}", self.kind_name())?; + + match *self { + ItemKind::Module(ref module) => module.dot_attributes(ctx, out), + ItemKind::Type(ref ty) => ty.dot_attributes(ctx, out), + ItemKind::Function(ref func) => func.dot_attributes(ctx, out), + ItemKind::Var(ref var) => var.dot_attributes(ctx, out), + } + } +} diff --git a/bindgen/ir/layout.rs b/bindgen/ir/layout.rs new file mode 100644 index 0000000000..ba570e3702 --- /dev/null +++ b/bindgen/ir/layout.rs @@ -0,0 +1,70 @@ +//! Intermediate representation for the physical layout of some type. + +use crate::ir::context::BindgenContext; + +/// A type that represents the struct layout of a type. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct Layout { + /// The size (in bytes) of this layout. + pub(crate) size: usize, + /// The alignment (in bytes) of this layout. + pub(crate) align: usize, + /// Whether this layout's members are packed or not. + pub(crate) packed: bool, +} + +#[test] +fn test_layout_for_size() { + use std::mem::size_of; + let ptr_size = size_of::<*mut ()>(); + assert_eq!( + Layout::for_size_internal(ptr_size, ptr_size), + Layout::new(ptr_size, ptr_size) + ); + assert_eq!( + Layout::for_size_internal(ptr_size, 3 * ptr_size), + Layout::new(3 * ptr_size, ptr_size) + ); +} + +impl Layout { + /// Gets the integer type name for a given known size. + pub(crate) fn known_type_for_size(size: usize) -> Option { + Some(match size { + 16 => syn::parse_quote! { u128 }, + 8 => syn::parse_quote! { u64 }, + 4 => syn::parse_quote! { u32 }, + 2 => syn::parse_quote! { u16 }, + 1 => syn::parse_quote! { u8 }, + _ => return None, + }) + } + + /// Construct a new `Layout` with the given `size` and `align`. It is not + /// packed. + pub(crate) fn new(size: usize, align: usize) -> Self { + Layout { + size, + align, + packed: false, + } + } + + fn for_size_internal(ptr_size: usize, size: usize) -> Self { + let mut next_align = 2; + while size % next_align == 0 && next_align <= ptr_size { + next_align *= 2; + } + Layout { + size, + align: next_align / 2, + packed: false, + } + } + + /// Creates a non-packed layout for a given size, trying to use the maximum + /// alignment possible. + pub(crate) fn for_size(ctx: &BindgenContext, size: usize) -> Self { + Self::for_size_internal(ctx.target_pointer_size(), size) + } +} diff --git a/bindgen/ir/mod.rs b/bindgen/ir/mod.rs new file mode 100644 index 0000000000..acdb4896cd --- /dev/null +++ b/bindgen/ir/mod.rs @@ -0,0 +1,25 @@ +//! The ir module defines bindgen's intermediate representation. +//! +//! Parsing C/C++ generates the IR, while code generation outputs Rust code from +//! the IR. +#![deny(clippy::missing_docs_in_private_items)] + +pub(crate) mod analysis; +pub(crate) mod annotations; +pub(crate) mod comment; +pub(crate) mod comp; +pub(crate) mod context; +pub(crate) mod derive; +pub(crate) mod dot; +pub(crate) mod enum_ty; +pub(crate) mod function; +pub(crate) mod int; +pub(crate) mod item; +pub(crate) mod item_kind; +pub(crate) mod layout; +pub(crate) mod module; +pub(crate) mod objc; +pub(crate) mod template; +pub(crate) mod traversal; +pub(crate) mod ty; +pub(crate) mod var; diff --git a/bindgen/ir/module.rs b/bindgen/ir/module.rs new file mode 100644 index 0000000000..4788cf4285 --- /dev/null +++ b/bindgen/ir/module.rs @@ -0,0 +1,96 @@ +//! Intermediate representation for modules (AKA C++ namespaces). + +use super::context::BindgenContext; +use super::dot::DotAttributes; +use super::item::ItemSet; +use crate::clang; +use crate::parse::{ClangSubItemParser, ParseError, ParseResult}; +use crate::parse_one; + +use std::io; + +/// Whether this module is inline or not. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum ModuleKind { + /// This module is not inline. + Normal, + /// This module is inline, as in `inline namespace foo {}`. + Inline, +} + +/// A module, as in, a C++ namespace. +#[derive(Clone, Debug)] +pub(crate) struct Module { + /// The name of the module, or none if it's anonymous. + name: Option, + /// The kind of module this is. + kind: ModuleKind, + /// The children of this module, just here for convenience. + children: ItemSet, +} + +impl Module { + /// Construct a new `Module`. + pub(crate) fn new(name: Option, kind: ModuleKind) -> Self { + Module { + name, + kind, + children: ItemSet::new(), + } + } + + /// Get this module's name. + pub(crate) fn name(&self) -> Option<&str> { + self.name.as_deref() + } + + /// Get a mutable reference to this module's children. + pub(crate) fn children_mut(&mut self) -> &mut ItemSet { + &mut self.children + } + + /// Get this module's children. + pub(crate) fn children(&self) -> &ItemSet { + &self.children + } + + /// Whether this namespace is inline. + pub(crate) fn is_inline(&self) -> bool { + self.kind == ModuleKind::Inline + } +} + +impl DotAttributes for Module { + fn dot_attributes( + &self, + _ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!(out, "ModuleKind{:?}", self.kind) + } +} + +impl ClangSubItemParser for Module { + fn parse( + cursor: clang::Cursor, + ctx: &mut BindgenContext, + ) -> Result, ParseError> { + use clang_sys::*; + match cursor.kind() { + CXCursor_Namespace => { + let module_id = ctx.module(cursor); + ctx.with_module(module_id, |ctx| { + cursor.visit_sorted(ctx, |ctx, child| { + parse_one(ctx, child, Some(module_id.into())); + }); + }); + + Ok(ParseResult::AlreadyResolved(module_id.into())) + } + _ => Err(ParseError::Continue), + } + } +} diff --git a/bindgen/ir/objc.rs b/bindgen/ir/objc.rs new file mode 100644 index 0000000000..6cdadb131d --- /dev/null +++ b/bindgen/ir/objc.rs @@ -0,0 +1,343 @@ +//! Objective C types + +use super::context::{BindgenContext, ItemId}; +use super::function::FunctionSig; +use super::item::Item; +use super::traversal::{Trace, Tracer}; +use super::ty::TypeKind; +use crate::clang; +use clang_sys::CXChildVisit_Continue; +use clang_sys::CXCursor_ObjCCategoryDecl; +use clang_sys::CXCursor_ObjCClassMethodDecl; +use clang_sys::CXCursor_ObjCClassRef; +use clang_sys::CXCursor_ObjCInstanceMethodDecl; +use clang_sys::CXCursor_ObjCProtocolDecl; +use clang_sys::CXCursor_ObjCProtocolRef; +use clang_sys::CXCursor_ObjCSuperClassRef; +use clang_sys::CXCursor_TemplateTypeParameter; +use proc_macro2::{Ident, Span, TokenStream}; + +/// Objective-C interface as used in `TypeKind` +/// +/// Also, protocols and categories are parsed as this type +#[derive(Debug)] +pub(crate) struct ObjCInterface { + /// The name + /// like, `NSObject` + name: String, + + category: Option, + + is_protocol: bool, + + /// The list of template names almost always, `ObjectType` or `KeyType` + pub(crate) template_names: Vec, + + /// The list of protocols that this interface conforms to. + pub(crate) conforms_to: Vec, + + /// The direct parent for this interface. + pub(crate) parent_class: Option, + + /// List of the methods defined in this interface + methods: Vec, + + class_methods: Vec, +} + +/// The objective c methods +#[derive(Debug)] +pub(crate) struct ObjCMethod { + /// The original method selector name + /// like, dataWithBytes:length: + name: String, + + /// Method name as converted to rust + /// like, `dataWithBytes_length`_ + rust_name: String, + + signature: FunctionSig, + + /// Is class method? + is_class_method: bool, +} + +impl ObjCInterface { + fn new(name: &str) -> ObjCInterface { + ObjCInterface { + name: name.to_owned(), + category: None, + is_protocol: false, + template_names: Vec::new(), + parent_class: None, + conforms_to: Vec::new(), + methods: Vec::new(), + class_methods: Vec::new(), + } + } + + /// The name + /// like, `NSObject` + pub(crate) fn name(&self) -> &str { + self.name.as_ref() + } + + /// Formats the name for rust + /// Can be like `NSObject`, but with categories might be like `NSObject_NSCoderMethods` + /// and protocols are like `PNSObject` + pub(crate) fn rust_name(&self) -> String { + if let Some(ref cat) = self.category { + format!("{}_{cat}", self.name()) + } else if self.is_protocol { + format!("P{}", self.name()) + } else { + format!("I{}", self.name().to_owned()) + } + } + + /// Is this a template interface? + pub(crate) fn is_template(&self) -> bool { + !self.template_names.is_empty() + } + + /// List of the methods defined in this interface + pub(crate) fn methods(&self) -> &Vec { + &self.methods + } + + /// Is this a protocol? + pub(crate) fn is_protocol(&self) -> bool { + self.is_protocol + } + + /// Is this a category? + pub(crate) fn is_category(&self) -> bool { + self.category.is_some() + } + + /// List of the class methods defined in this interface + pub(crate) fn class_methods(&self) -> &Vec { + &self.class_methods + } + + /// Parses the Objective C interface from the cursor + pub(crate) fn from_ty( + cursor: &clang::Cursor, + ctx: &mut BindgenContext, + ) -> Option { + let name = cursor.spelling(); + let mut interface = Self::new(&name); + + if cursor.kind() == CXCursor_ObjCProtocolDecl { + interface.is_protocol = true; + } + + cursor.visit(|c| { + match c.kind() { + CXCursor_ObjCClassRef => { + if cursor.kind() == CXCursor_ObjCCategoryDecl { + // We are actually a category extension, and we found the reference + // to the original interface, so name this interface appropriately + interface.name = c.spelling(); + interface.category = Some(cursor.spelling()); + } + } + CXCursor_ObjCProtocolRef => { + // Gather protocols this interface conforms to + let needle = format!("P{}", c.spelling()); + let items_map = ctx.items(); + debug!( + "Interface {} conforms to {needle}, find the item", + interface.name, + ); + + for (id, item) in items_map { + if let Some(ty) = item.as_type() { + if let TypeKind::ObjCInterface(ref protocol) = + *ty.kind() + { + if protocol.is_protocol { + debug!( + "Checking protocol {}, ty.name {:?}", + protocol.name, + ty.name() + ); + if Some(needle.as_ref()) == ty.name() { + debug!("Found conforming protocol {item:?}"); + interface.conforms_to.push(id); + break; + } + } + } + } + } + } + CXCursor_ObjCInstanceMethodDecl | + CXCursor_ObjCClassMethodDecl => { + let name = c.spelling(); + let signature = + FunctionSig::from_ty(&c.cur_type(), &c, ctx) + .expect("Invalid function sig"); + let is_class_method = + c.kind() == CXCursor_ObjCClassMethodDecl; + let method = + ObjCMethod::new(&name, signature, is_class_method); + interface.add_method(method); + } + CXCursor_TemplateTypeParameter => { + let name = c.spelling(); + interface.template_names.push(name); + } + CXCursor_ObjCSuperClassRef => { + let item = Item::from_ty_or_ref(c.cur_type(), c, None, ctx); + interface.parent_class = Some(item.into()); + } + _ => {} + } + CXChildVisit_Continue + }); + Some(interface) + } + + fn add_method(&mut self, method: ObjCMethod) { + if method.is_class_method { + self.class_methods.push(method); + } else { + self.methods.push(method); + } + } +} + +impl ObjCMethod { + fn new( + name: &str, + signature: FunctionSig, + is_class_method: bool, + ) -> ObjCMethod { + let split_name: Vec<&str> = name.split(':').collect(); + + let rust_name = split_name.join("_"); + + ObjCMethod { + name: name.to_owned(), + rust_name, + signature, + is_class_method, + } + } + + /// Method name as converted to rust + /// like, `dataWithBytes_length`_ + pub(crate) fn rust_name(&self) -> &str { + self.rust_name.as_ref() + } + + /// Returns the methods signature as `FunctionSig` + pub(crate) fn signature(&self) -> &FunctionSig { + &self.signature + } + + /// Is this a class method? + pub(crate) fn is_class_method(&self) -> bool { + self.is_class_method + } + + /// Formats the method call + pub(crate) fn format_method_call( + &self, + args: &[TokenStream], + ) -> TokenStream { + let split_name: Vec> = self + .name + .split(':') + .enumerate() + .map(|(idx, name)| { + if name.is_empty() { + None + } else if idx == 0 { + // Try to parse the method name as an identifier. Having a keyword is ok + // unless it is `crate`, `self`, `super` or `Self`, so we try to add the `_` + // suffix to it and parse it. + if ["crate", "self", "super", "Self"].contains(&name) { + Some(Ident::new(&format!("{name}_"), Span::call_site())) + } else { + Some(Ident::new(name, Span::call_site())) + } + } else { + // Try to parse the current joining name as an identifier. This might fail if the name + // is a keyword, so we try to "r#" to it and parse again, this could also fail + // if the name is `crate`, `self`, `super` or `Self`, so we try to add the `_` + // suffix to it and parse again. If this also fails, we panic with the first + // error. + Some( + syn::parse_str::(name) + .or_else(|err| { + syn::parse_str::(&format!("r#{name}")) + .map_err(|_| err) + }) + .or_else(|err| { + syn::parse_str::(&format!("{name}_")) + .map_err(|_| err) + }) + .expect("Invalid identifier"), + ) + } + }) + .collect(); + + // No arguments + if args.is_empty() && split_name.len() == 1 { + let name = &split_name[0]; + return quote! { + #name + }; + } + + // Check right amount of arguments + assert_eq!(args.len(), split_name.len() - 1, "Incorrect method name or arguments for objc method, {args:?} vs {split_name:?}"); + + // Get arguments without type signatures to pass to `msg_send!` + let mut args_without_types = vec![]; + for arg in args { + let arg = arg.to_string(); + let name_and_sig: Vec<&str> = arg.split(' ').collect(); + let name = name_and_sig[0]; + args_without_types.push(Ident::new(name, Span::call_site())); + } + + let args = split_name.into_iter().zip(args_without_types).map( + |(arg, arg_val)| { + if let Some(arg) = arg { + quote! { #arg: #arg_val } + } else { + quote! { #arg_val: #arg_val } + } + }, + ); + + quote! { + #( #args )* + } + } +} + +impl Trace for ObjCInterface { + type Extra = (); + + fn trace(&self, context: &BindgenContext, tracer: &mut T, _: &()) + where + T: Tracer, + { + for method in &self.methods { + method.signature.trace(context, tracer, &()); + } + + for class_method in &self.class_methods { + class_method.signature.trace(context, tracer, &()); + } + + for protocol in &self.conforms_to { + tracer.visit(*protocol); + } + } +} diff --git a/bindgen/ir/template.rs b/bindgen/ir/template.rs new file mode 100644 index 0000000000..7f3667879d --- /dev/null +++ b/bindgen/ir/template.rs @@ -0,0 +1,335 @@ +//! Template declaration and instantiation related things. +//! +//! The nomenclature surrounding templates is often confusing, so here are a few +//! brief definitions: +//! +//! * "Template definition": a class/struct/alias/function definition that takes +//! generic template parameters. For example: +//! +//! ```c++ +//! template +//! class List { +//! // ... +//! }; +//! ``` +//! +//! * "Template instantiation": an instantiation is a use of a template with +//! concrete template arguments. For example, `List`. +//! +//! * "Template specialization": an alternative template definition providing a +//! custom definition for instantiations with the matching template +//! arguments. This C++ feature is unsupported by bindgen. For example: +//! +//! ```c++ +//! template<> +//! class List { +//! // Special layout for int lists... +//! }; +//! ``` + +use super::context::{BindgenContext, ItemId, TypeId}; +use super::item::{IsOpaque, Item, ItemAncestors}; +use super::traversal::{EdgeKind, Trace, Tracer}; +use crate::clang; + +/// Template declaration (and such declaration's template parameters) related +/// methods. +/// +/// This trait's methods distinguish between `None` and `Some([])` for +/// declarations that are not templates and template declarations with zero +/// parameters, in general. +/// +/// Consider this example: +/// +/// ```c++ +/// template +/// class Foo { +/// T use_of_t; +/// U use_of_u; +/// +/// template +/// using Bar = V*; +/// +/// class Inner { +/// T x; +/// U y; +/// Bar z; +/// }; +/// +/// template +/// class Lol { +/// // No use of W, but here's a use of T. +/// T t; +/// }; +/// +/// template +/// class Wtf { +/// // X is not used because W is not used. +/// Lol lololol; +/// }; +/// }; +/// +/// class Qux { +/// int y; +/// }; +/// ``` +/// +/// The following table depicts the results of each trait method when invoked on +/// each of the declarations above: +/// +/// |Decl. | self_template_params | num_self_template_params | all_template_parameters | +/// |------|----------------------|--------------------------|-------------------------| +/// |Foo | T, U | 2 | T, U | +/// |Bar | V | 1 | T, U, V | +/// |Inner | | 0 | T, U | +/// |Lol | W | 1 | T, U, W | +/// |Wtf | X | 1 | T, U, X | +/// |Qux | | 0 | | +/// +/// | Decl. | used_template_params | +/// |-------|----------------------| +/// | Foo | T, U | +/// | Bar | V | +/// | Inner | | +/// | Lol | T | +/// | Wtf | T | +/// | Qux | | +pub(crate) trait TemplateParameters: Sized { + /// Get the set of `ItemId`s that make up this template declaration's free + /// template parameters. + /// + /// Note that these might *not* all be named types: C++ allows + /// constant-value template parameters as well as template-template + /// parameters. Of course, Rust does not allow generic parameters to be + /// anything but types, so we must treat them as opaque, and avoid + /// instantiating them. + fn self_template_params(&self, ctx: &BindgenContext) -> Vec; + + /// Get the number of free template parameters this template declaration + /// has. + fn num_self_template_params(&self, ctx: &BindgenContext) -> usize { + self.self_template_params(ctx).len() + } + + /// Get the complete set of template parameters that can affect this + /// declaration. + /// + /// Note that this item doesn't need to be a template declaration itself for + /// `Some` to be returned here (in contrast to `self_template_params`). If + /// this item is a member of a template declaration, then the parent's + /// template parameters are included here. + /// + /// In the example above, `Inner` depends on both of the `T` and `U` type + /// parameters, even though it is not itself a template declaration and + /// therefore has no type parameters itself. Perhaps it helps to think about + /// how we would fully reference such a member type in C++: + /// `Foo::Inner`. `Foo` *must* be instantiated with template + /// arguments before we can gain access to the `Inner` member type. + fn all_template_params(&self, ctx: &BindgenContext) -> Vec + where + Self: ItemAncestors, + { + let mut ancestors: Vec<_> = self.ancestors(ctx).collect(); + ancestors.reverse(); + ancestors + .into_iter() + .flat_map(|id| id.self_template_params(ctx).into_iter()) + .collect() + } + + /// Get only the set of template parameters that this item uses. This is a + /// subset of `all_template_params` and does not necessarily contain any of + /// `self_template_params`. + fn used_template_params(&self, ctx: &BindgenContext) -> Vec + where + Self: AsRef, + { + assert!( + ctx.in_codegen_phase(), + "template parameter usage is not computed until codegen" + ); + + let id = *self.as_ref(); + ctx.resolve_item(id) + .all_template_params(ctx) + .into_iter() + .filter(|p| ctx.uses_template_parameter(id, *p)) + .collect() + } +} + +/// A trait for things which may or may not be a named template type parameter. +pub(crate) trait AsTemplateParam { + /// Any extra information the implementor might need to make this decision. + type Extra; + + /// Convert this thing to the item ID of a named template type parameter. + fn as_template_param( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> Option; + + /// Is this a named template type parameter? + fn is_template_param( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> bool { + self.as_template_param(ctx, extra).is_some() + } +} + +/// A concrete instantiation of a generic template. +#[derive(Clone, Debug)] +pub(crate) struct TemplateInstantiation { + /// The template definition which this is instantiating. + definition: TypeId, + /// The concrete template arguments, which will be substituted in the + /// definition for the generic template parameters. + args: Vec, +} + +impl TemplateInstantiation { + /// Construct a new template instantiation from the given parts. + pub(crate) fn new(definition: TypeId, args: I) -> TemplateInstantiation + where + I: IntoIterator, + { + TemplateInstantiation { + definition, + args: args.into_iter().collect(), + } + } + + /// Get the template definition for this instantiation. + pub(crate) fn template_definition(&self) -> TypeId { + self.definition + } + + /// Get the concrete template arguments used in this instantiation. + pub(crate) fn template_arguments(&self) -> &[TypeId] { + &self.args[..] + } + + /// Parse a `TemplateInstantiation` from a clang `Type`. + pub(crate) fn from_ty( + ty: &clang::Type, + ctx: &mut BindgenContext, + ) -> Option { + use clang_sys::*; + + let template_args = ty.template_args().map_or(vec![], |args| match ty + .canonical_type() + .template_args() + { + Some(canonical_args) => { + let arg_count = args.len(); + args.chain(canonical_args.skip(arg_count)) + .filter(|t| t.kind() != CXType_Invalid) + .map(|t| { + Item::from_ty_or_ref(t, t.declaration(), None, ctx) + }) + .collect() + } + None => args + .filter(|t| t.kind() != CXType_Invalid) + .map(|t| Item::from_ty_or_ref(t, t.declaration(), None, ctx)) + .collect(), + }); + + let declaration = ty.declaration(); + let definition = if declaration.kind() == CXCursor_TypeAliasTemplateDecl + { + Some(declaration) + } else { + declaration.specialized().or_else(|| { + let mut template_ref = None; + ty.declaration().visit(|child| { + if child.kind() == CXCursor_TemplateRef { + template_ref = Some(child); + return CXVisit_Break; + } + + // Instantiations of template aliases might have the + // TemplateRef to the template alias definition arbitrarily + // deep, so we need to recurse here and not only visit + // direct children. + CXChildVisit_Recurse + }); + + template_ref.and_then(|cur| cur.referenced()) + }) + }; + + let Some(definition) = definition else { + if !ty.declaration().is_builtin() { + warn!( + "Could not find template definition for template \ + instantiation" + ); + } + return None; + }; + + let template_definition = + Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx); + + Some(TemplateInstantiation::new( + template_definition, + template_args, + )) + } +} + +impl IsOpaque for TemplateInstantiation { + type Extra = Item; + + /// Is this an opaque template instantiation? + fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { + if self.template_definition().is_opaque(ctx, &()) { + return true; + } + + // TODO(#774): This doesn't properly handle opaque instantiations where + // an argument is itself an instantiation because `canonical_name` does + // not insert the template arguments into the name, ie it for nested + // template arguments it creates "Foo" instead of "Foo". The fully + // correct fix is to make `canonical_{name,path}` include template + // arguments properly. + + let mut path = item.path_for_allowlisting(ctx).clone(); + let args: Vec<_> = self + .template_arguments() + .iter() + .map(|arg| { + let arg_path = + ctx.resolve_item(*arg).path_for_allowlisting(ctx); + arg_path[1..].join("::") + }) + .collect(); + { + let last = path.last_mut().unwrap(); + last.push('<'); + last.push_str(&args.join(", ")); + last.push('>'); + } + + ctx.opaque_by_name(&path) + } +} + +impl Trace for TemplateInstantiation { + type Extra = (); + + fn trace(&self, _ctx: &BindgenContext, tracer: &mut T, _: &()) + where + T: Tracer, + { + tracer + .visit_kind(self.definition.into(), EdgeKind::TemplateDeclaration); + for arg in self.template_arguments() { + tracer.visit_kind(arg.into(), EdgeKind::TemplateArgument); + } + } +} diff --git a/src/ir/traversal.rs b/bindgen/ir/traversal.rs similarity index 80% rename from src/ir/traversal.rs rename to bindgen/ir/traversal.rs index c37b0b5f85..01f3a8bd50 100644 --- a/src/ir/traversal.rs +++ b/bindgen/ir/traversal.rs @@ -12,31 +12,28 @@ use std::collections::{BTreeMap, VecDeque}; /// The `from` is left implicit: it is the concrete `Trace` implementer which /// yielded this outgoing edge. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Edge { +pub(crate) struct Edge { to: ItemId, kind: EdgeKind, } impl Edge { /// Construct a new edge whose referent is `to` and is of the given `kind`. - pub fn new(to: ItemId, kind: EdgeKind) -> Edge { - Edge { - to, - kind, - } + pub(crate) fn new(to: ItemId, kind: EdgeKind) -> Edge { + Edge { to, kind } } } -impl Into for Edge { - fn into(self) -> ItemId { - self.to +impl From for ItemId { + fn from(val: Edge) -> Self { + val.to } } /// The kind of edge reference. This is useful when we wish to only consider /// certain kinds of edges for a particular traversal or analysis. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum EdgeKind { +pub(crate) enum EdgeKind { /// A generic, catch-all edge. Generic, @@ -182,38 +179,32 @@ pub enum EdgeKind { /// A predicate to allow visiting only sub-sets of the whole IR graph by /// excluding certain edges from being followed by the traversal. -pub trait TraversalPredicate { - /// Should the traversal follow this edge, and visit everything that is - /// reachable through it? - fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool; -} - -impl TraversalPredicate for for<'a> fn(&'a BindgenContext, Edge) -> bool { - fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool { - (*self)(ctx, edge) - } -} +/// +/// The predicate must return true if the traversal should follow this edge +/// and visit everything that is reachable through it. +pub(crate) type TraversalPredicate = + for<'a> fn(&'a BindgenContext, Edge) -> bool; /// A `TraversalPredicate` implementation that follows all edges, and therefore /// traversals using this predicate will see the whole IR graph reachable from /// the traversal's roots. -pub fn all_edges(_: &BindgenContext, _: Edge) -> bool { +pub(crate) fn all_edges(_: &BindgenContext, _: Edge) -> bool { true } /// A `TraversalPredicate` implementation that only follows /// `EdgeKind::InnerType` edges, and therefore traversals using this predicate /// will only visit the traversal's roots and their inner types. This is used -/// in no-recursive-whitelist mode, where inner types such as anonymous +/// in no-recursive-allowlist mode, where inner types such as anonymous /// structs/unions still need to be processed. -pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool { +pub(crate) fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool { edge.kind == EdgeKind::InnerType } /// A `TraversalPredicate` implementation that only follows edges to items that /// are enabled for code generation. This lets us skip considering items for /// which are not reachable from code generation. -pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool { +pub(crate) fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool { let cc = &ctx.options().codegen_config; match edge.kind { EdgeKind::Generic => { @@ -232,19 +223,19 @@ pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool { EdgeKind::FunctionReturn | EdgeKind::FunctionParameter | EdgeKind::VarType | - EdgeKind::TypeReference => cc.types, - EdgeKind::InnerVar => cc.vars, - EdgeKind::Method => cc.methods, - EdgeKind::Constructor => cc.constructors, - EdgeKind::Destructor => cc.destructors, + EdgeKind::TypeReference => cc.types(), + EdgeKind::InnerVar => cc.vars(), + EdgeKind::Method => cc.methods(), + EdgeKind::Constructor => cc.constructors(), + EdgeKind::Destructor => cc.destructors(), } } /// The storage for the set of items that have been seen (although their /// outgoing edges might not have been fully traversed yet) in an active /// traversal. -pub trait TraversalStorage<'ctx> { - /// Construct a new instance of this TraversalStorage, for a new traversal. +pub(crate) trait TraversalStorage<'ctx> { + /// Construct a new instance of this `TraversalStorage`, for a new traversal. fn new(ctx: &'ctx BindgenContext) -> Self; /// Add the given item to the storage. If the item has never been seen @@ -269,10 +260,7 @@ impl<'ctx> TraversalStorage<'ctx> for ItemSet { /// each item. This is useful for providing debug assertions with meaningful /// diagnostic messages about dangling items. #[derive(Debug)] -pub struct Paths<'ctx>( - BTreeMap, - &'ctx BindgenContext -); +pub(crate) struct Paths<'ctx>(BTreeMap, &'ctx BindgenContext); impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> { fn new(ctx: &'ctx BindgenContext) -> Self { @@ -289,7 +277,7 @@ impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> { loop { let predecessor = *self.0.get(¤t).expect( "We know we found this item id, so it must have a \ - predecessor", + predecessor", ); if predecessor == current { break; @@ -299,9 +287,7 @@ impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> { } path.reverse(); panic!( - "Found reference to dangling id = {:?}\nvia path = {:?}", - item, - path + "Found reference to dangling id = {item:?}\nvia path = {path:?}" ); } @@ -314,7 +300,7 @@ impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> { /// Using a FIFO queue with a traversal will yield a breadth-first traversal, /// while using a LIFO queue will result in a depth-first traversal of the IR /// graph. -pub trait TraversalQueue: Default { +pub(crate) trait TraversalQueue: Default { /// Add a newly discovered item to the queue. fn push(&mut self, item: ItemId); @@ -343,7 +329,7 @@ impl TraversalQueue for VecDeque { } /// Something that can receive edges from a `Trace` implementation. -pub trait Tracer { +pub(crate) trait Tracer { /// Note an edge between items. Called from within a `Trace` implementation. fn visit_kind(&mut self, item: ItemId, kind: EdgeKind); @@ -358,14 +344,14 @@ where F: FnMut(ItemId, EdgeKind), { fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) { - (*self)(item, kind) + (*self)(item, kind); } } /// Trace all of the outgoing edges to other items. Implementations should call /// one of `tracer.visit(edge)` or `tracer.visit_kind(edge, EdgeKind::Whatever)` /// for each of their outgoing edges. -pub trait Trace { +pub(crate) trait Trace { /// If a particular type needs extra information beyond what it has in /// `self` and `context` to find its referenced items, its implementation /// can define this associated type, forcing callers to pass the needed @@ -384,12 +370,11 @@ pub trait Trace { /// An graph traversal of the transitive closure of references between items. /// -/// See `BindgenContext::whitelisted_items` for more information. -pub struct ItemTraversal<'ctx, Storage, Queue, Predicate> +/// See `BindgenContext::allowlisted_items` for more information. +pub(crate) struct ItemTraversal<'ctx, Storage, Queue> where Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, - Predicate: TraversalPredicate, { ctx: &'ctx BindgenContext, @@ -400,25 +385,23 @@ where queue: Queue, /// The predicate that determines which edges this traversal will follow. - predicate: Predicate, + predicate: TraversalPredicate, /// The item we are currently traversing. currently_traversing: Option, } -impl<'ctx, Storage, Queue, Predicate> - ItemTraversal<'ctx, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue> ItemTraversal<'ctx, Storage, Queue> where Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, - Predicate: TraversalPredicate, { /// Begin a new traversal, starting from the given roots. - pub fn new( + pub(crate) fn new( ctx: &'ctx BindgenContext, roots: R, - predicate: Predicate, - ) -> ItemTraversal<'ctx, Storage, Queue, Predicate> + predicate: TraversalPredicate, + ) -> ItemTraversal<'ctx, Storage, Queue> where R: IntoIterator, { @@ -431,42 +414,38 @@ where } ItemTraversal { - ctx: ctx, - seen: seen, - queue: queue, - predicate: predicate, + ctx, + seen, + queue, + predicate, currently_traversing: None, } } } -impl<'ctx, Storage, Queue, Predicate> Tracer - for ItemTraversal<'ctx, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue> Tracer for ItemTraversal<'ctx, Storage, Queue> where Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, - Predicate: TraversalPredicate, { fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) { let edge = Edge::new(item, kind); - if !self.predicate.should_follow(self.ctx, edge) { + if !(self.predicate)(self.ctx, edge) { return; } let is_newly_discovered = self.seen.add(self.currently_traversing, item); if is_newly_discovered { - self.queue.push(item) + self.queue.push(item); } } } -impl<'ctx, Storage, Queue, Predicate> Iterator - for ItemTraversal<'ctx, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue> Iterator for ItemTraversal<'ctx, Storage, Queue> where Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, - Predicate: TraversalPredicate, { type Item = ItemId; @@ -495,22 +474,5 @@ where /// /// See `BindgenContext::assert_no_dangling_item_traversal` for more /// information. -pub type AssertNoDanglingItemsTraversal<'ctx> = - ItemTraversal< - 'ctx, - Paths<'ctx>, - VecDeque, - for<'a> fn(&'a BindgenContext, Edge) -> bool, - >; - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[allow(dead_code)] - fn traversal_predicate_is_object_safe() { - // This should compile only if TraversalPredicate is object safe. - fn takes_by_trait_object(_: &TraversalPredicate) {} - } -} +pub(crate) type AssertNoDanglingItemsTraversal<'ctx> = + ItemTraversal<'ctx, Paths<'ctx>, VecDeque>; diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs new file mode 100644 index 0000000000..a53de31c6a --- /dev/null +++ b/bindgen/ir/ty.rs @@ -0,0 +1,1267 @@ +//! Everything related to types in our intermediate representation. + +use super::comp::CompInfo; +use super::context::{BindgenContext, ItemId, TypeId}; +use super::dot::DotAttributes; +use super::enum_ty::Enum; +use super::function::FunctionSig; +use super::item::{IsOpaque, Item}; +use super::layout::Layout; +use super::objc::ObjCInterface; +use super::template::{ + AsTemplateParam, TemplateInstantiation, TemplateParameters, +}; +use super::traversal::{EdgeKind, Trace, Tracer}; +use crate::clang::{self, Cursor}; +use crate::parse::{ParseError, ParseResult}; +use std::borrow::Cow; +use std::io; + +pub use super::int::IntKind; + +/// The base representation of a type in bindgen. +/// +/// A type has an optional name, which if present cannot be empty, a `layout` +/// (size, alignment and packedness) if known, a `Kind`, which determines which +/// kind of type it is, and whether the type is const. +#[derive(Debug)] +pub(crate) struct Type { + /// The name of the type, or None if it was an unnamed struct or union. + name: Option, + /// The layout of the type, if known. + layout: Option, + /// The inner kind of the type + kind: TypeKind, + /// Whether this type is const-qualified. + is_const: bool, +} + +/// The maximum number of items in an array for which Rust implements common +/// traits, and so if we have a type containing an array with more than this +/// many items, we won't be able to derive common traits on that type. +/// +pub(crate) const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32; + +impl Type { + /// Get the underlying `CompInfo` for this type as a mutable reference, or + /// `None` if this is some other kind of type. + pub(crate) fn as_comp_mut(&mut self) -> Option<&mut CompInfo> { + match self.kind { + TypeKind::Comp(ref mut ci) => Some(ci), + _ => None, + } + } + + /// Construct a new `Type`. + pub(crate) fn new( + name: Option, + layout: Option, + kind: TypeKind, + is_const: bool, + ) -> Self { + Type { + name, + layout, + kind, + is_const, + } + } + + /// Construct an opaque item from a clang type. + pub(crate) fn new_opaque_from_clang_ty( + ty: &clang::Type, + ctx: &BindgenContext, + ) -> Self { + let layout = Layout::new(ty.size(ctx), ty.align(ctx)); + let ty_kind = TypeKind::Opaque; + let is_const = ty.is_const(); + Type::new(None, Some(layout), ty_kind, is_const) + } + + /// Which kind of type is this? + pub(crate) fn kind(&self) -> &TypeKind { + &self.kind + } + + /// Get a mutable reference to this type's kind. + pub(crate) fn kind_mut(&mut self) -> &mut TypeKind { + &mut self.kind + } + + /// Get this type's name. + pub(crate) fn name(&self) -> Option<&str> { + self.name.as_deref() + } + + /// Whether this is a block pointer type. + pub(crate) fn is_block_pointer(&self) -> bool { + matches!(self.kind, TypeKind::BlockPointer(..)) + } + + /// Is this an integer type, including `bool` or `char`? + pub(crate) fn is_int(&self) -> bool { + matches!(self.kind, TypeKind::Int(_)) + } + + /// Is this a compound type? + pub(crate) fn is_comp(&self) -> bool { + matches!(self.kind, TypeKind::Comp(..)) + } + + /// Is this a union? + pub(crate) fn is_union(&self) -> bool { + match self.kind { + TypeKind::Comp(ref comp) => comp.is_union(), + _ => false, + } + } + + /// Is this type of kind `TypeKind::TypeParam`? + pub(crate) fn is_type_param(&self) -> bool { + matches!(self.kind, TypeKind::TypeParam) + } + + /// Is this a template instantiation type? + pub(crate) fn is_template_instantiation(&self) -> bool { + matches!(self.kind, TypeKind::TemplateInstantiation(..)) + } + + /// Is this a function type? + pub(crate) fn is_function(&self) -> bool { + matches!(self.kind, TypeKind::Function(..)) + } + + /// Is this an enum type? + pub(crate) fn is_enum(&self) -> bool { + matches!(self.kind, TypeKind::Enum(..)) + } + + /// Is this void? + pub(crate) fn is_void(&self) -> bool { + matches!(self.kind, TypeKind::Void) + } + /// Is this either a builtin or named type? + pub(crate) fn is_builtin_or_type_param(&self) -> bool { + matches!( + self.kind, + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Function(..) | + TypeKind::Array(..) | + TypeKind::Reference(..) | + TypeKind::Pointer(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::TypeParam + ) + } + + /// Creates a new named type, with name `name`. + pub(crate) fn named(name: String) -> Self { + let name = if name.is_empty() { None } else { Some(name) }; + Self::new(name, None, TypeKind::TypeParam, false) + } + + /// Is this a floating point type? + pub(crate) fn is_float(&self) -> bool { + matches!(self.kind, TypeKind::Float(..)) + } + + /// Is this a boolean type? + pub(crate) fn is_bool(&self) -> bool { + matches!(self.kind, TypeKind::Int(IntKind::Bool)) + } + + /// Is this an integer type? + pub(crate) fn is_integer(&self) -> bool { + matches!(self.kind, TypeKind::Int(..)) + } + + /// Cast this type to an integer kind, or `None` if it is not an integer + /// type. + pub(crate) fn as_integer(&self) -> Option { + match self.kind { + TypeKind::Int(int_kind) => Some(int_kind), + _ => None, + } + } + + /// Is this a `const` qualified type? + pub(crate) fn is_const(&self) -> bool { + self.is_const + } + + /// Is this an unresolved reference? + pub(crate) fn is_unresolved_ref(&self) -> bool { + matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _)) + } + + /// Is this a incomplete array type? + pub(crate) fn is_incomplete_array( + &self, + ctx: &BindgenContext, + ) -> Option { + match self.kind { + TypeKind::Array(item, len) => { + if len == 0 { + Some(item.into()) + } else { + None + } + } + TypeKind::ResolvedTypeRef(inner) => { + ctx.resolve_type(inner).is_incomplete_array(ctx) + } + _ => None, + } + } + + /// What is the layout of this type? + pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option { + self.layout.or_else(|| { + match self.kind { + TypeKind::Comp(ref ci) => ci.layout(ctx), + TypeKind::Array(inner, 0) => Some(Layout::new( + 0, + ctx.resolve_type(inner).layout(ctx)?.align, + )), + // FIXME(emilio): This is a hack for anonymous union templates. + // Use the actual pointer size! + TypeKind::Pointer(..) => Some(Layout::new( + ctx.target_pointer_size(), + ctx.target_pointer_size(), + )), + TypeKind::ResolvedTypeRef(inner) => { + ctx.resolve_type(inner).layout(ctx) + } + _ => None, + } + }) + } + + /// Whether this named type is an invalid C++ identifier. This is done to + /// avoid generating invalid code with some cases we can't handle, see: + /// + /// tests/headers/381-decltype-alias.hpp + pub(crate) fn is_invalid_type_param(&self) -> bool { + match self.kind { + TypeKind::TypeParam => { + let name = self.name().expect("Unnamed named type?"); + !clang::is_valid_identifier(name) + } + _ => false, + } + } + + /// Takes `name`, and returns a suitable identifier representation for it. + fn sanitize_name(name: &str) -> Cow<'_, str> { + if clang::is_valid_identifier(name) { + return Cow::Borrowed(name); + } + + let name = name.replace([' ', ':', '.'], "_"); + Cow::Owned(name) + } + + /// Get this type's sanitized name. + pub(crate) fn sanitized_name<'a>( + &'a self, + ctx: &BindgenContext, + ) -> Option> { + let name_info = match *self.kind() { + TypeKind::Pointer(inner) => Some((inner, Cow::Borrowed("ptr"))), + TypeKind::Reference(inner) => Some((inner, Cow::Borrowed("ref"))), + TypeKind::Array(inner, length) => { + Some((inner, format!("array{length}").into())) + } + _ => None, + }; + if let Some((inner, prefix)) = name_info { + ctx.resolve_item(inner) + .expect_type() + .sanitized_name(ctx) + .map(|name| format!("{prefix}_{name}").into()) + } else { + self.name().map(Self::sanitize_name) + } + } + + /// See [`Self::safe_canonical_type`]. + pub(crate) fn canonical_type<'tr>( + &'tr self, + ctx: &'tr BindgenContext, + ) -> &'tr Type { + self.safe_canonical_type(ctx) + .expect("Should have been resolved after parsing!") + } + + /// Returns the canonical type of this type, that is, the "inner type". + /// + /// For example, for a `typedef`, the canonical type would be the + /// `typedef`ed type, for a template instantiation, would be the template + /// its specializing, and so on. Return None if the type is unresolved. + pub(crate) fn safe_canonical_type<'tr>( + &'tr self, + ctx: &'tr BindgenContext, + ) -> Option<&'tr Type> { + match self.kind { + TypeKind::TypeParam | + TypeKind::Array(..) | + TypeKind::Vector(..) | + TypeKind::Comp(..) | + TypeKind::Opaque | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Pointer(..) | + TypeKind::BlockPointer(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::ObjCInterface(..) => Some(self), + + TypeKind::ResolvedTypeRef(inner) | + TypeKind::Alias(inner) | + TypeKind::TemplateAlias(inner, _) => { + ctx.resolve_type(inner).safe_canonical_type(ctx) + } + TypeKind::TemplateInstantiation(ref inst) => ctx + .resolve_type(inst.template_definition()) + .safe_canonical_type(ctx), + + TypeKind::UnresolvedTypeRef(..) => None, + } + } + + /// There are some types we don't want to stop at when finding an opaque + /// item, so we can arrive to the proper item that needs to be generated. + pub(crate) fn should_be_traced_unconditionally(&self) -> bool { + matches!( + self.kind, + TypeKind::Comp(..) | + TypeKind::Function(..) | + TypeKind::Pointer(..) | + TypeKind::Array(..) | + TypeKind::Reference(..) | + TypeKind::TemplateInstantiation(..) | + TypeKind::ResolvedTypeRef(..) + ) + } +} + +impl IsOpaque for Type { + type Extra = Item; + + fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { + match self.kind { + TypeKind::Opaque => true, + TypeKind::TemplateInstantiation(ref inst) => { + inst.is_opaque(ctx, item) + } + TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &self.layout), + TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()), + _ => false, + } + } +} + +impl AsTemplateParam for Type { + type Extra = Item; + + fn as_template_param( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> Option { + self.kind.as_template_param(ctx, item) + } +} + +impl AsTemplateParam for TypeKind { + type Extra = Item; + + fn as_template_param( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> Option { + match *self { + TypeKind::TypeParam => Some(item.id().expect_type_id(ctx)), + TypeKind::ResolvedTypeRef(id) => id.as_template_param(ctx, &()), + _ => None, + } + } +} + +impl DotAttributes for Type { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + if let Some(ref layout) = self.layout { + writeln!( + out, + "size{} + align{}", + layout.size, layout.align + )?; + if layout.packed { + writeln!(out, "packedtrue")?; + } + } + + if self.is_const { + writeln!(out, "consttrue")?; + } + + self.kind.dot_attributes(ctx, out) + } +} + +impl DotAttributes for TypeKind { + fn dot_attributes( + &self, + ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + writeln!( + out, + "type kind{}", + self.kind_name() + )?; + + if let TypeKind::Comp(ref comp) = *self { + comp.dot_attributes(ctx, out)?; + } + + Ok(()) + } +} + +impl TypeKind { + fn kind_name(&self) -> &'static str { + match *self { + TypeKind::Void => "Void", + TypeKind::NullPtr => "NullPtr", + TypeKind::Comp(..) => "Comp", + TypeKind::Opaque => "Opaque", + TypeKind::Int(..) => "Int", + TypeKind::Float(..) => "Float", + TypeKind::Complex(..) => "Complex", + TypeKind::Alias(..) => "Alias", + TypeKind::TemplateAlias(..) => "TemplateAlias", + TypeKind::Array(..) => "Array", + TypeKind::Vector(..) => "Vector", + TypeKind::Function(..) => "Function", + TypeKind::Enum(..) => "Enum", + TypeKind::Pointer(..) => "Pointer", + TypeKind::BlockPointer(..) => "BlockPointer", + TypeKind::Reference(..) => "Reference", + TypeKind::TemplateInstantiation(..) => "TemplateInstantiation", + TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef", + TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef", + TypeKind::TypeParam => "TypeParam", + TypeKind::ObjCInterface(..) => "ObjCInterface", + TypeKind::ObjCId => "ObjCId", + TypeKind::ObjCSel => "ObjCSel", + } + } +} + +#[test] +fn is_invalid_type_param_valid() { + let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false); + assert!(!ty.is_invalid_type_param()); +} + +#[test] +fn is_invalid_type_param_valid_underscore_and_numbers() { + let ty = Type::new( + Some("_foo123456789_".into()), + None, + TypeKind::TypeParam, + false, + ); + assert!(!ty.is_invalid_type_param()); +} + +#[test] +fn is_invalid_type_param_valid_unnamed_kind() { + let ty = Type::new(Some("foo".into()), None, TypeKind::Void, false); + assert!(!ty.is_invalid_type_param()); +} + +#[test] +fn is_invalid_type_param_invalid_start() { + let ty = Type::new(Some("1foo".into()), None, TypeKind::TypeParam, false); + assert!(ty.is_invalid_type_param()); +} + +#[test] +fn is_invalid_type_param_invalid_remaining() { + let ty = Type::new(Some("foo-".into()), None, TypeKind::TypeParam, false); + assert!(ty.is_invalid_type_param()); +} + +#[test] +#[should_panic(expected = "Unnamed named type")] +fn is_invalid_type_param_unnamed() { + let ty = Type::new(None, None, TypeKind::TypeParam, false); + assert!(ty.is_invalid_type_param()); +} + +#[test] +fn is_invalid_type_param_empty_name() { + let ty = Type::new(Some(String::new()), None, TypeKind::TypeParam, false); + assert!(ty.is_invalid_type_param()); +} + +impl TemplateParameters for Type { + fn self_template_params(&self, ctx: &BindgenContext) -> Vec { + self.kind.self_template_params(ctx) + } +} + +impl TemplateParameters for TypeKind { + fn self_template_params(&self, ctx: &BindgenContext) -> Vec { + match *self { + TypeKind::ResolvedTypeRef(id) => { + ctx.resolve_type(id).self_template_params(ctx) + } + TypeKind::Comp(ref comp) => comp.self_template_params(ctx), + TypeKind::TemplateAlias(_, ref args) => args.clone(), + + TypeKind::Opaque | + TypeKind::TemplateInstantiation(..) | + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(_) | + TypeKind::Float(_) | + TypeKind::Complex(_) | + TypeKind::Array(..) | + TypeKind::Vector(..) | + TypeKind::Function(_) | + TypeKind::Enum(_) | + TypeKind::Pointer(_) | + TypeKind::BlockPointer(_) | + TypeKind::Reference(_) | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::TypeParam | + TypeKind::Alias(_) | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::ObjCInterface(_) => vec![], + } + } +} + +/// The kind of float this type represents. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum FloatKind { + /// A half (`_Float16` or `__fp16`) + Float16, + /// A `float`. + Float, + /// A `double`. + Double, + /// A `long double`. + LongDouble, + /// A `__float128`. + Float128, +} + +/// The different kinds of types that we can parse. +#[derive(Debug)] +pub(crate) enum TypeKind { + /// The void type. + Void, + + /// The `nullptr_t` type. + NullPtr, + + /// A compound type, that is, a class, struct, or union. + Comp(CompInfo), + + /// An opaque type that we just don't understand. All usage of this should + /// result in an opaque blob of bytes generated from the containing type's + /// layout. + Opaque, + + /// An integer type, of a given kind. `bool` and `char` are also considered + /// integers. + Int(IntKind), + + /// A floating point type. + Float(FloatKind), + + /// A complex floating point type. + Complex(FloatKind), + + /// A type alias, with a name, that points to another type. + Alias(TypeId), + + /// A templated alias, pointing to an inner type, just as `Alias`, but with + /// template parameters. + TemplateAlias(TypeId, Vec), + + /// A packed vector type: element type, number of elements + Vector(TypeId, usize), + + /// An array of a type and a length. + Array(TypeId, usize), + + /// A function type, with a given signature. + Function(FunctionSig), + + /// An `enum` type. + Enum(Enum), + + /// A pointer to a type. The bool field represents whether it's const or + /// not. + Pointer(TypeId), + + /// A pointer to an Apple block. + BlockPointer(TypeId), + + /// A reference to a type, as in: int& `foo()`. + Reference(TypeId), + + /// An instantiation of an abstract template definition with a set of + /// concrete template arguments. + TemplateInstantiation(TemplateInstantiation), + + /// A reference to a yet-to-resolve type. This stores the clang cursor + /// itself, and postpones its resolution. + /// + /// These are gone in a phase after parsing where these are mapped to + /// already known types, and are converted to `ResolvedTypeRef`. + /// + /// see tests/headers/typeref.hpp to see somewhere where this is a problem. + UnresolvedTypeRef(clang::Type, Cursor, /* parent_id */ Option), + + /// An indirection to another type. + /// + /// These are generated after we resolve a forward declaration, or when we + /// replace one type with another. + ResolvedTypeRef(TypeId), + + /// A named type, that is, a template parameter. + TypeParam, + + /// Objective C interface. Always referenced through a pointer + ObjCInterface(ObjCInterface), + + /// Objective C 'id' type, points to any object + ObjCId, + + /// Objective C selector type + ObjCSel, +} + +impl Type { + /// This is another of the nasty methods. This one is the one that takes + /// care of the core logic of converting a clang type to a `Type`. + /// + /// It's sort of nasty and full of special-casing, but hopefully the + /// comments in every special case justify why they're there. + pub(crate) fn from_clang_ty( + potential_id: ItemId, + ty: &clang::Type, + location: Cursor, + parent_id: Option, + ctx: &mut BindgenContext, + ) -> Result, ParseError> { + use clang_sys::*; + { + let already_resolved = ctx.builtin_or_resolved_ty( + potential_id, + parent_id, + ty, + Some(location), + ); + if let Some(ty) = already_resolved { + debug!("{ty:?} already resolved: {location:?}"); + return Ok(ParseResult::AlreadyResolved(ty.into())); + } + } + + let layout = ty.fallible_layout(ctx).ok(); + let cursor = ty.declaration(); + let is_anonymous = cursor.is_anonymous(); + let mut name = if is_anonymous { + None + } else { + Some(cursor.spelling()).filter(|n| !n.is_empty()) + }; + + debug!( + "from_clang_ty: {potential_id:?}, ty: {ty:?}, loc: {location:?}" + ); + debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types()); + + let canonical_ty = ty.canonical_type(); + + // Parse objc protocols as if they were interfaces + let mut ty_kind = ty.kind(); + match location.kind() { + CXCursor_ObjCProtocolDecl | CXCursor_ObjCCategoryDecl => { + ty_kind = CXType_ObjCInterface; + } + _ => {} + } + + // Objective C template type parameter + // FIXME: This is probably wrong, we are attempting to find the + // objc template params, which seem to manifest as a typedef. + // We are rewriting them as ID to suppress multiple conflicting + // typedefs at root level + if ty_kind == CXType_Typedef { + let is_template_type_param = + ty.declaration().kind() == CXCursor_TemplateTypeParameter; + let is_canonical_objcpointer = + canonical_ty.kind() == CXType_ObjCObjectPointer; + + // We have found a template type for objc interface + if is_canonical_objcpointer && is_template_type_param { + // Objective-C generics are just ids with fancy name. + // To keep it simple, just name them ids + name = Some("id".to_owned()); + } + } + + if location.kind() == CXCursor_ClassTemplatePartialSpecialization { + // Sorry! (Not sorry) + warn!( + "Found a partial template specialization; bindgen does not \ + support partial template specialization! Constructing \ + opaque type instead." + ); + return Ok(ParseResult::New( + Self::new_opaque_from_clang_ty(&canonical_ty, ctx), + None, + )); + } + + let kind = if location.kind() == CXCursor_TemplateRef || + (ty.template_args().is_some() && ty_kind != CXType_Typedef) + { + // This is a template instantiation. + match TemplateInstantiation::from_ty(ty, ctx) { + Some(inst) => TypeKind::TemplateInstantiation(inst), + None => TypeKind::Opaque, + } + } else { + match ty_kind { + CXType_Unexposed + if *ty != canonical_ty && + canonical_ty.kind() != CXType_Invalid && + ty.ret_type().is_none() && + // Sometime clang desugars some types more than + // what we need, specially with function + // pointers. + // + // We should also try the solution of inverting + // those checks instead of doing this, that is, + // something like: + // + // CXType_Unexposed if ty.ret_type().is_some() + // => { ... } + // + // etc. + !canonical_ty.spelling().contains("type-parameter") => + { + debug!("Looking for canonical type: {canonical_ty:?}"); + return Self::from_clang_ty( + potential_id, + &canonical_ty, + location, + parent_id, + ctx, + ); + } + CXType_Unexposed | CXType_Invalid => { + // For some reason Clang doesn't give us any hint in some + // situations where we should generate a function pointer (see + // tests/headers/func_ptr_in_struct.h), so we do a guess here + // trying to see if it has a valid return type. + if ty.ret_type().is_some() { + let signature = + FunctionSig::from_ty(ty, &location, ctx)?; + TypeKind::Function(signature) + // Same here, with template specialisations we can safely + // assume this is a Comp(..) + } else if ty.is_fully_instantiated_template() { + debug!("Template specialization: {ty:?}, {location:?} {canonical_ty:?}"); + let complex = CompInfo::from_ty( + potential_id, + ty, + Some(location), + ctx, + ) + .expect("C'mon"); + TypeKind::Comp(complex) + } else { + match location.kind() { + CXCursor_CXXBaseSpecifier | + CXCursor_ClassTemplate => { + if location.kind() == CXCursor_CXXBaseSpecifier + { + // In the case we're parsing a base specifier + // inside an unexposed or invalid type, it means + // that we're parsing one of two things: + // + // * A template parameter. + // * A complex class that isn't exposed. + // + // This means, unfortunately, that there's no + // good way to differentiate between them. + // + // Probably we could try to look at the + // declaration and complicate more this logic, + // but we'll keep it simple... if it's a valid + // C++ identifier, we'll consider it as a + // template parameter. + // + // This is because: + // + // * We expect every other base that is a + // proper identifier (that is, a simple + // struct/union declaration), to be exposed, + // so this path can't be reached in that + // case. + // + // * Quite conveniently, complex base + // specifiers preserve their full names (that + // is: Foo instead of Foo). We can take + // advantage of this. + // + // If we find some edge case where this doesn't + // work (which I guess is unlikely, see the + // different test cases[1][2][3][4]), we'd need + // to find more creative ways of differentiating + // these two cases. + // + // [1]: inherit_named.hpp + // [2]: forward-inherit-struct-with-fields.hpp + // [3]: forward-inherit-struct.hpp + // [4]: inherit-namespaced.hpp + if location.spelling().chars().all(|c| { + c.is_alphanumeric() || c == '_' + }) { + return Err(ParseError::Recurse); + } + } else { + name = Some(location.spelling()); + } + + let complex = CompInfo::from_ty( + potential_id, + ty, + Some(location), + ctx, + ); + if let Ok(complex) = complex { + TypeKind::Comp(complex) + } else { + warn!( + "Could not create complex type \ + from class template or base \ + specifier, using opaque blob" + ); + let opaque = + Self::new_opaque_from_clang_ty(ty, ctx); + return Ok(ParseResult::New(opaque, None)); + } + } + CXCursor_TypeAliasTemplateDecl => { + debug!("TypeAliasTemplateDecl"); + + // We need to manually unwind this one. + let mut inner = Err(ParseError::Continue); + let mut args = vec![]; + + location.visit(|cur| { + match cur.kind() { + CXCursor_TypeAliasDecl => { + let current = cur.cur_type(); + + debug_assert_eq!( + current.kind(), + CXType_Typedef + ); + + name = Some(location.spelling()); + + let inner_ty = cur + .typedef_type() + .expect("Not valid Type?"); + inner = Ok(Item::from_ty_or_ref( + inner_ty, + cur, + Some(potential_id), + ctx, + )); + } + CXCursor_TemplateTypeParameter => { + let param = Item::type_param( + None, cur, ctx, + ) + .expect( + "Item::type_param shouldn't \ + ever fail if we are looking \ + at a TemplateTypeParameter", + ); + args.push(param); + } + _ => {} + } + CXChildVisit_Continue + }); + + let Ok(inner_type) = inner else { + warn!( + "Failed to parse template alias \ + {location:?}" + ); + return Err(ParseError::Continue); + }; + + TypeKind::TemplateAlias(inner_type, args) + } + CXCursor_TemplateRef => { + let referenced = location.referenced().unwrap(); + let referenced_ty = referenced.cur_type(); + + debug!("TemplateRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}"); + + return Self::from_clang_ty( + potential_id, + &referenced_ty, + referenced, + parent_id, + ctx, + ); + } + CXCursor_TypeRef => { + let referenced = location.referenced().unwrap(); + let referenced_ty = referenced.cur_type(); + let declaration = referenced_ty.declaration(); + + debug!("TypeRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}"); + + let id = Item::from_ty_or_ref_with_id( + potential_id, + referenced_ty, + declaration, + parent_id, + ctx, + ); + return Ok(ParseResult::AlreadyResolved( + id.into(), + )); + } + CXCursor_NamespaceRef => { + return Err(ParseError::Continue); + } + _ => { + if ty.kind() == CXType_Unexposed { + warn!("Unexposed type {ty:?}, recursing inside, loc: {location:?}"); + return Err(ParseError::Recurse); + } + + warn!("invalid type {ty:?}"); + return Err(ParseError::Continue); + } + } + } + } + CXType_Auto => { + if canonical_ty == *ty { + debug!("Couldn't find deduced type: {ty:?}"); + return Err(ParseError::Continue); + } + + return Self::from_clang_ty( + potential_id, + &canonical_ty, + location, + parent_id, + ctx, + ); + } + // NOTE: We don't resolve pointers eagerly because the pointee type + // might not have been parsed, and if it contains templates or + // something else we might get confused, see the comment inside + // TypeRef. + // + // We might need to, though, if the context is already in the + // process of resolving them. + CXType_ObjCObjectPointer | + CXType_MemberPointer | + CXType_Pointer => { + let mut pointee = ty.pointee_type().unwrap(); + if *ty != canonical_ty { + let canonical_pointee = + canonical_ty.pointee_type().unwrap(); + // clang sometimes loses pointee constness here, see + // #2244. + if canonical_pointee.is_const() != pointee.is_const() { + pointee = canonical_pointee; + } + } + let inner = + Item::from_ty_or_ref(pointee, location, None, ctx); + TypeKind::Pointer(inner) + } + CXType_BlockPointer => { + let pointee = ty.pointee_type().expect("Not valid Type?"); + let inner = + Item::from_ty_or_ref(pointee, location, None, ctx); + TypeKind::BlockPointer(inner) + } + // XXX: RValueReference is most likely wrong, but I don't think we + // can even add bindings for that, so huh. + CXType_RValueReference | CXType_LValueReference => { + let inner = Item::from_ty_or_ref( + ty.pointee_type().unwrap(), + location, + None, + ctx, + ); + TypeKind::Reference(inner) + } + // XXX DependentSizedArray is wrong + CXType_VariableArray | CXType_DependentSizedArray => { + let inner = Item::from_ty( + ty.elem_type().as_ref().unwrap(), + location, + None, + ctx, + ) + .expect("Not able to resolve array element?"); + TypeKind::Pointer(inner) + } + CXType_IncompleteArray => { + let inner = Item::from_ty( + ty.elem_type().as_ref().unwrap(), + location, + None, + ctx, + ) + .expect("Not able to resolve array element?"); + TypeKind::Array(inner, 0) + } + CXType_FunctionNoProto | CXType_FunctionProto => { + let signature = FunctionSig::from_ty(ty, &location, ctx)?; + TypeKind::Function(signature) + } + CXType_Typedef => { + let inner = cursor.typedef_type().expect("Not valid Type?"); + let inner_id = + Item::from_ty_or_ref(inner, location, None, ctx); + if inner_id == potential_id { + warn!( + "Generating opaque type instead of self-referential \ + typedef"); + // This can happen if we bail out of recursive situations + // within the clang parsing. + TypeKind::Opaque + } else { + // Check if this type definition is an alias to a pointer of a `struct` / + // `union` / `enum` with the same name and add the `_ptr` suffix to it to + // avoid name collisions. + if let Some(ref mut name) = name { + if inner.kind() == CXType_Pointer && + !ctx.options().c_naming + { + let pointee = inner.pointee_type().unwrap(); + if pointee.kind() == CXType_Elaborated && + pointee.declaration().spelling() == *name + { + *name += "_ptr"; + } + } + } + TypeKind::Alias(inner_id) + } + } + CXType_Enum => { + let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?"); + + if !is_anonymous { + let pretty_name = ty.spelling(); + if clang::is_valid_identifier(&pretty_name) { + name = Some(pretty_name); + } + } + + TypeKind::Enum(enum_) + } + CXType_Record => { + let complex = CompInfo::from_ty( + potential_id, + ty, + Some(location), + ctx, + ) + .expect("Not a complex type?"); + + if !is_anonymous { + // The pretty-printed name may contain typedefed name, + // but may also be "struct (anonymous at .h:1)" + let pretty_name = ty.spelling(); + if clang::is_valid_identifier(&pretty_name) { + name = Some(pretty_name); + } + } + + TypeKind::Comp(complex) + } + CXType_Vector | CXType_ExtVector => { + let inner = Item::from_ty( + ty.elem_type().as_ref().unwrap(), + location, + None, + ctx, + )?; + TypeKind::Vector(inner, ty.num_elements().unwrap()) + } + CXType_ConstantArray => { + let inner = Item::from_ty( + ty.elem_type().as_ref().unwrap(), + location, + None, + ctx, + ) + .expect("Not able to resolve array element?"); + TypeKind::Array(inner, ty.num_elements().unwrap()) + } + CXType_Atomic => { + // TODO(emilio): Maybe we can preserve the "is atomic" bit somehow and generate + // something more useful... But for now this is better than panicking or + // generating nothing. + return Self::from_clang_ty( + potential_id, + &ty.atomic_value_type(), + location, + parent_id, + ctx, + ); + } + CXType_Elaborated => { + return Self::from_clang_ty( + potential_id, + &ty.named(), + location, + parent_id, + ctx, + ); + } + CXType_ObjCId => TypeKind::ObjCId, + CXType_ObjCSel => TypeKind::ObjCSel, + CXType_ObjCClass | CXType_ObjCInterface => { + let interface = ObjCInterface::from_ty(&location, ctx) + .expect("Not a valid objc interface?"); + if !is_anonymous { + name = Some(interface.rust_name()); + } + TypeKind::ObjCInterface(interface) + } + CXType_Dependent => { + return Err(ParseError::Continue); + } + _ => { + warn!( + "unsupported type: kind = {:?}; ty = {ty:?}; at {location:?}", + ty.kind(), + ); + return Err(ParseError::Continue); + } + } + }; + + name = name.filter(|n| !n.is_empty()); + + let is_const = ty.is_const() || + (ty.kind() == CXType_ConstantArray && + ty.elem_type().is_some_and(|element| element.is_const())); + + let ty = Type::new(name, layout, kind, is_const); + // TODO: maybe declaration.canonical()? + Ok(ParseResult::New(ty, Some(cursor.canonical()))) + } +} + +impl Trace for Type { + type Extra = Item; + + fn trace(&self, context: &BindgenContext, tracer: &mut T, item: &Item) + where + T: Tracer, + { + if self.name().is_some_and(|name| context.is_stdint_type(name)) { + // These types are special-cased in codegen and don't need to be traversed. + return; + } + match *self.kind() { + TypeKind::Pointer(inner) | + TypeKind::Reference(inner) | + TypeKind::Array(inner, _) | + TypeKind::Vector(inner, _) | + TypeKind::BlockPointer(inner) | + TypeKind::Alias(inner) | + TypeKind::ResolvedTypeRef(inner) => { + tracer.visit_kind(inner.into(), EdgeKind::TypeReference); + } + TypeKind::TemplateAlias(inner, ref template_params) => { + tracer.visit_kind(inner.into(), EdgeKind::TypeReference); + for param in template_params { + tracer.visit_kind( + param.into(), + EdgeKind::TemplateParameterDefinition, + ); + } + } + TypeKind::TemplateInstantiation(ref inst) => { + inst.trace(context, tracer, &()); + } + TypeKind::Comp(ref ci) => ci.trace(context, tracer, item), + TypeKind::Function(ref sig) => sig.trace(context, tracer, &()), + TypeKind::Enum(ref en) => { + if let Some(repr) = en.repr() { + tracer.visit(repr.into()); + } + } + TypeKind::UnresolvedTypeRef(_, _, Some(id)) => { + tracer.visit(id); + } + + TypeKind::ObjCInterface(ref interface) => { + interface.trace(context, tracer, &()); + } + + // None of these variants have edges to other items and types. + TypeKind::Opaque | + TypeKind::UnresolvedTypeRef(_, _, None) | + TypeKind::TypeParam | + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(_) | + TypeKind::Float(_) | + TypeKind::Complex(_) | + TypeKind::ObjCId | + TypeKind::ObjCSel => {} + } + } +} diff --git a/bindgen/ir/var.rs b/bindgen/ir/var.rs new file mode 100644 index 0000000000..9d72dcf06e --- /dev/null +++ b/bindgen/ir/var.rs @@ -0,0 +1,523 @@ +//! Intermediate representation of variables. + +use super::super::codegen::MacroTypeVariation; +use super::context::{BindgenContext, TypeId}; +use super::dot::DotAttributes; +use super::function::cursor_mangling; +use super::int::IntKind; +use super::item::Item; +use super::ty::{FloatKind, TypeKind}; +use crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior}; +use crate::clang; +use crate::clang::ClangToken; +use crate::parse::{ClangSubItemParser, ParseError, ParseResult}; + +use std::io; +use std::num::Wrapping; + +/// The type for a constant variable. +#[derive(Debug)] +pub(crate) enum VarType { + /// A boolean. + Bool(bool), + /// An integer. + Int(i64), + /// A floating point number. + Float(f64), + /// A character. + Char(u8), + /// A string, not necessarily well-formed utf-8. + String(Vec), +} + +/// A `Var` is our intermediate representation of a variable. +#[derive(Debug)] +pub(crate) struct Var { + /// The name of the variable. + name: String, + /// The mangled name of the variable. + mangled_name: Option, + /// The link name of the variable. + link_name: Option, + /// The type of the variable. + ty: TypeId, + /// The value of the variable, that needs to be suitable for `ty`. + val: Option, + /// Whether this variable is const. + is_const: bool, +} + +impl Var { + /// Construct a new `Var`. + pub(crate) fn new( + name: String, + mangled_name: Option, + link_name: Option, + ty: TypeId, + val: Option, + is_const: bool, + ) -> Var { + assert!(!name.is_empty()); + Var { + name, + mangled_name, + link_name, + ty, + val, + is_const, + } + } + + /// Is this variable `const` qualified? + pub(crate) fn is_const(&self) -> bool { + self.is_const + } + + /// The value of this constant variable, if any. + pub(crate) fn val(&self) -> Option<&VarType> { + self.val.as_ref() + } + + /// Get this variable's type. + pub(crate) fn ty(&self) -> TypeId { + self.ty + } + + /// Get this variable's name. + pub(crate) fn name(&self) -> &str { + &self.name + } + + /// Get this variable's mangled name. + pub(crate) fn mangled_name(&self) -> Option<&str> { + self.mangled_name.as_deref() + } + + /// Get this variable's link name. + pub fn link_name(&self) -> Option<&str> { + self.link_name.as_deref() + } +} + +impl DotAttributes for Var { + fn dot_attributes( + &self, + _ctx: &BindgenContext, + out: &mut W, + ) -> io::Result<()> + where + W: io::Write, + { + if self.is_const { + writeln!(out, "consttrue")?; + } + + if let Some(ref mangled) = self.mangled_name { + writeln!(out, "mangled name{mangled}")?; + } + + Ok(()) + } +} + +fn default_macro_constant_type(ctx: &BindgenContext, value: i64) -> IntKind { + if value < 0 || + ctx.options().default_macro_constant_type == + MacroTypeVariation::Signed + { + if value < i64::from(i32::MIN) || value > i64::from(i32::MAX) { + IntKind::I64 + } else if !ctx.options().fit_macro_constants || + value < i64::from(i16::MIN) || + value > i64::from(i16::MAX) + { + IntKind::I32 + } else if value < i64::from(i8::MIN) || value > i64::from(i8::MAX) { + IntKind::I16 + } else { + IntKind::I8 + } + } else if value > i64::from(u32::MAX) { + IntKind::U64 + } else if !ctx.options().fit_macro_constants || value > i64::from(u16::MAX) + { + IntKind::U32 + } else if value > i64::from(u8::MAX) { + IntKind::U16 + } else { + IntKind::U8 + } +} + +/// Parses tokens from a `CXCursor_MacroDefinition` pointing into a function-like +/// macro, and calls the `func_macro` callback. +fn handle_function_macro( + cursor: &clang::Cursor, + callbacks: &dyn crate::callbacks::ParseCallbacks, +) { + let is_closing_paren = |t: &ClangToken| { + // Test cheap token kind before comparing exact spellings. + t.kind == clang_sys::CXToken_Punctuation && t.spelling() == b")" + }; + let tokens: Vec<_> = cursor.tokens().iter().collect(); + if let Some(boundary) = tokens.iter().position(is_closing_paren) { + let mut spelled = tokens.iter().map(ClangToken::spelling); + // Add 1, to convert index to length. + let left = spelled.by_ref().take(boundary + 1); + let left = left.collect::>().concat(); + if let Ok(left) = String::from_utf8(left) { + let right: Vec<_> = spelled.collect(); + callbacks.func_macro(&left, &right); + } + } +} + +impl ClangSubItemParser for Var { + fn parse( + cursor: clang::Cursor, + ctx: &mut BindgenContext, + ) -> Result, ParseError> { + use cexpr::expr::EvalResult; + use cexpr::literal::CChar; + use clang_sys::*; + match cursor.kind() { + CXCursor_MacroDefinition => { + for callbacks in &ctx.options().parse_callbacks { + match callbacks.will_parse_macro(&cursor.spelling()) { + MacroParsingBehavior::Ignore => { + return Err(ParseError::Continue); + } + MacroParsingBehavior::Default => {} + } + + if cursor.is_macro_function_like() { + handle_function_macro(&cursor, callbacks.as_ref()); + // We handled the macro, skip macro processing below. + return Err(ParseError::Continue); + } + } + + let value = parse_macro(ctx, &cursor); + + let Some((id, value)) = value else { + return Err(ParseError::Continue); + }; + + assert!(!id.is_empty(), "Empty macro name?"); + + let previously_defined = ctx.parsed_macro(&id); + + // NB: It's important to "note" the macro even if the result is + // not an integer, otherwise we might loose other kind of + // derived macros. + ctx.note_parsed_macro(id.clone(), value.clone()); + + if previously_defined { + let name = String::from_utf8(id).unwrap(); + duplicated_macro_diagnostic(&name, cursor.location(), ctx); + return Err(ParseError::Continue); + } + + // NOTE: Unwrapping, here and above, is safe, because the + // identifier of a token comes straight from clang, and we + // enforce utf8 there, so we should have already panicked at + // this point. + let name = String::from_utf8(id).unwrap(); + let (type_kind, val) = match value { + EvalResult::Invalid => return Err(ParseError::Continue), + EvalResult::Float(f) => { + (TypeKind::Float(FloatKind::Double), VarType::Float(f)) + } + EvalResult::Char(c) => { + let c = match c { + CChar::Char(c) => { + assert_eq!(c.len_utf8(), 1); + c as u8 + } + CChar::Raw(c) => u8::try_from(c).unwrap(), + }; + + (TypeKind::Int(IntKind::U8), VarType::Char(c)) + } + EvalResult::Str(val) => { + let char_ty = Item::builtin_type( + TypeKind::Int(IntKind::U8), + true, + ctx, + ); + for callbacks in &ctx.options().parse_callbacks { + callbacks.str_macro(&name, &val); + } + (TypeKind::Pointer(char_ty), VarType::String(val)) + } + EvalResult::Int(Wrapping(value)) => { + let kind = ctx + .options() + .last_callback(|c| c.int_macro(&name, value)) + .unwrap_or_else(|| { + default_macro_constant_type(ctx, value) + }); + + (TypeKind::Int(kind), VarType::Int(value)) + } + }; + + let ty = Item::builtin_type(type_kind, true, ctx); + + Ok(ParseResult::New( + Var::new(name, None, None, ty, Some(val), true), + Some(cursor), + )) + } + CXCursor_VarDecl => { + let mut name = cursor.spelling(); + if cursor.linkage() == CXLinkage_External { + if let Some(nm) = ctx.options().last_callback(|callbacks| { + callbacks.generated_name_override(ItemInfo { + name: name.as_str(), + kind: ItemKind::Var, + }) + }) { + name = nm; + } + } + // No more changes to name + let name = name; + + if name.is_empty() { + warn!("Empty constant name?"); + return Err(ParseError::Continue); + } + + let link_name = ctx.options().last_callback(|callbacks| { + callbacks.generated_link_name_override(ItemInfo { + name: name.as_str(), + kind: ItemKind::Var, + }) + }); + + let ty = cursor.cur_type(); + + // TODO(emilio): do we have to special-case constant arrays in + // some other places? + let is_const = ty.is_const() || + ([CXType_ConstantArray, CXType_IncompleteArray] + .contains(&ty.kind()) && + ty.elem_type() + .is_some_and(|element| element.is_const())); + + let ty = match Item::from_ty(&ty, cursor, None, ctx) { + Ok(ty) => ty, + Err(e) => { + assert!( + matches!(ty.kind(), CXType_Auto | CXType_Unexposed), + "Couldn't resolve constant type, and it \ + wasn't an nondeductible auto type or unexposed \ + type: {ty:?}" + ); + return Err(e); + } + }; + + // Note: Ty might not be totally resolved yet, see + // tests/headers/inner_const.hpp + // + // That's fine because in that case we know it's not a literal. + let canonical_ty = ctx + .safe_resolve_type(ty) + .and_then(|t| t.safe_canonical_type(ctx)); + + let is_integer = canonical_ty.is_some_and(|t| t.is_integer()); + let is_float = canonical_ty.is_some_and(|t| t.is_float()); + + // TODO: We could handle `char` more gracefully. + // TODO: Strings, though the lookup is a bit more hard (we need + // to look at the canonical type of the pointee too, and check + // is char, u8, or i8 I guess). + let value = if is_integer { + let TypeKind::Int(kind) = *canonical_ty.unwrap().kind() + else { + unreachable!() + }; + + let mut val = cursor.evaluate().and_then(|v| v.as_int()); + if val.is_none() { + val = get_integer_literal_from_cursor(&cursor); + } + + val.map(|val| { + if kind == IntKind::Bool { + VarType::Bool(val != 0) + } else { + VarType::Int(val) + } + }) + } else if is_float { + cursor + .evaluate() + .and_then(|v| v.as_double()) + .map(VarType::Float) + } else { + cursor + .evaluate() + .and_then(|v| v.as_literal_string()) + .map(VarType::String) + }; + + let mangling = cursor_mangling(ctx, &cursor); + let var = + Var::new(name, mangling, link_name, ty, value, is_const); + + Ok(ParseResult::New(var, Some(cursor))) + } + _ => { + /* TODO */ + Err(ParseError::Continue) + } + } + } +} + +/// This function uses a [`FallbackTranslationUnit`][clang::FallbackTranslationUnit] to parse each +/// macro that cannot be parsed by the normal bindgen process for `#define`s. +/// +/// To construct the [`FallbackTranslationUnit`][clang::FallbackTranslationUnit], first precompiled +/// headers are generated for all input headers. An empty temporary `.c` file is generated to pass +/// to the translation unit. On the evaluation of each macro, a [`String`] is generated with the +/// new contents of the empty file and passed in for reparsing. The precompiled headers and +/// preservation of the [`FallbackTranslationUnit`][clang::FallbackTranslationUnit] across macro +/// evaluations are both optimizations that have significantly improved the performance. +fn parse_macro_clang_fallback( + ctx: &mut BindgenContext, + cursor: &clang::Cursor, +) -> Option<(Vec, cexpr::expr::EvalResult)> { + if !ctx.options().clang_macro_fallback { + return None; + } + + let ftu = ctx.try_ensure_fallback_translation_unit()?; + let contents = format!("int main() {{ {}; }}", cursor.spelling()); + ftu.reparse(&contents).ok()?; + // Children of root node of AST + let root_children = ftu.translation_unit().cursor().collect_children(); + // Last child in root is function declaration + // Should be FunctionDecl + let main_func = root_children.last()?; + // Children should all be statements in function declaration + let all_stmts = main_func.collect_children(); + // First child in all_stmts should be the statement containing the macro to evaluate + // Should be CompoundStmt + let macro_stmt = all_stmts.first()?; + // Children should all be expressions from the compound statement + let paren_exprs = macro_stmt.collect_children(); + // First child in all_exprs is the expression utilizing the given macro to be evaluated + // Should be ParenExpr + let paren = paren_exprs.first()?; + + Some(( + cursor.spelling().into_bytes(), + cexpr::expr::EvalResult::Int(Wrapping(paren.evaluate()?.as_int()?)), + )) +} + +/// Try and parse a macro using all the macros parsed until now. +fn parse_macro( + ctx: &mut BindgenContext, + cursor: &clang::Cursor, +) -> Option<(Vec, cexpr::expr::EvalResult)> { + use cexpr::expr; + + let mut cexpr_tokens = cursor.cexpr_tokens(); + + for callbacks in &ctx.options().parse_callbacks { + callbacks.modify_macro(&cursor.spelling(), &mut cexpr_tokens); + } + + let parser = expr::IdentifierParser::new(ctx.parsed_macros()); + + match parser.macro_definition(&cexpr_tokens) { + Ok((_, (id, val))) => Some((id.into(), val)), + _ => parse_macro_clang_fallback(ctx, cursor), + } +} + +fn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option { + use cexpr::expr; + use cexpr::expr::EvalResult; + + let cexpr_tokens = cursor.cexpr_tokens(); + + // TODO(emilio): We can try to parse other kinds of literals. + match expr::expr(&cexpr_tokens) { + Ok((_, EvalResult::Int(Wrapping(val)))) => Some(val), + _ => None, + } +} + +fn get_integer_literal_from_cursor(cursor: &clang::Cursor) -> Option { + use clang_sys::*; + let mut value = None; + cursor.visit(|c| { + match c.kind() { + CXCursor_IntegerLiteral | CXCursor_UnaryOperator => { + value = parse_int_literal_tokens(&c); + } + CXCursor_UnexposedExpr => { + value = get_integer_literal_from_cursor(&c); + } + _ => (), + } + if value.is_some() { + CXChildVisit_Break + } else { + CXChildVisit_Continue + } + }); + value +} + +fn duplicated_macro_diagnostic( + macro_name: &str, + _location: clang::SourceLocation, + _ctx: &BindgenContext, +) { + warn!("Duplicated macro definition: {macro_name}"); + + #[cfg(feature = "experimental")] + // FIXME (pvdrz & amanjeev): This diagnostic message shows way too often to be actually + // useful. We have to change the logic where this function is called to be able to emit this + // message only when the duplication is an actual issue. + // + // If I understood correctly, `bindgen` ignores all `#undef` directives. Meaning that this: + // ```c + // #define FOO 1 + // #undef FOO + // #define FOO 2 + // ``` + // + // Will trigger this message even though there's nothing wrong with it. + #[allow(clippy::overly_complex_bool_expr)] + if false && _ctx.options().emit_diagnostics { + use crate::diagnostics::{get_line, Diagnostic, Level, Slice}; + use std::borrow::Cow; + + let mut slice = Slice::default(); + let mut source = Cow::from(macro_name); + + let (file, line, col, _) = _location.location(); + if let Some(filename) = file.name() { + if let Ok(Some(code)) = get_line(&filename, line) { + source = code.into(); + } + slice.with_location(filename, line, col); + } + + slice.with_source(source); + + Diagnostic::default() + .with_title("Duplicated macro definition.", Level::Warning) + .add_slice(slice) + .add_annotation("This macro had a duplicate.", Level::Note) + .display(); + } +} diff --git a/bindgen/lib.rs b/bindgen/lib.rs new file mode 100644 index 0000000000..f2c8870e05 --- /dev/null +++ b/bindgen/lib.rs @@ -0,0 +1,1420 @@ +//! Generate Rust bindings for C and C++ libraries. +//! +//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++ +//! functions and use types defined in the header. +//! +//! See the [`Builder`](./struct.Builder.html) struct for usage. +//! +//! See the [Users Guide](https://rust-lang.github.io/rust-bindgen/) for +//! additional documentation. +#![deny(missing_docs)] +#![deny(unused_extern_crates)] +#![deny(clippy::disallowed_methods)] +// To avoid rather annoying warnings when matching with CXCursor_xxx as a +// constant. +#![allow(non_upper_case_globals)] +// `quote!` nests quite deeply. +#![recursion_limit = "128"] + +#[macro_use] +extern crate bitflags; +#[macro_use] +extern crate quote; + +#[cfg(feature = "logging")] +#[macro_use] +extern crate log; + +#[cfg(not(feature = "logging"))] +#[macro_use] +mod log_stubs; + +#[macro_use] +mod extra_assertions; + +mod codegen; +mod deps; +mod options; +mod time; + +pub mod callbacks; + +mod clang; +#[cfg(feature = "experimental")] +mod diagnostics; +mod features; +mod ir; +mod parse; +mod regex_set; + +pub use codegen::{ + AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle, +}; +pub use features::{RustEdition, RustTarget, LATEST_STABLE_RUST}; +pub use ir::annotations::FieldVisibilityKind; +pub use ir::function::Abi; +#[cfg(feature = "__cli")] +pub use options::cli::builder_from_flags; + +use codegen::CodegenError; +use features::RustFeatures; +use ir::comment; +use ir::context::{BindgenContext, ItemId}; +use ir::item::Item; +use options::BindgenOptions; +use parse::ParseError; + +use std::borrow::Cow; +use std::collections::hash_map::Entry; +use std::env; +use std::ffi::OsStr; +use std::fs::{File, OpenOptions}; +use std::io::{self, Write}; +use std::mem::size_of; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::rc::Rc; +use std::str::FromStr; + +// Some convenient typedefs for a fast hash map and hash set. +type HashMap = rustc_hash::FxHashMap; +type HashSet = rustc_hash::FxHashSet; + +/// Default prefix for the anon fields. +pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_"; + +const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern"; + +fn file_is_cpp(name_file: &str) -> bool { + Path::new(name_file).extension().is_some_and(|ext| { + ext.eq_ignore_ascii_case("hpp") || + ext.eq_ignore_ascii_case("hxx") || + ext.eq_ignore_ascii_case("hh") || + ext.eq_ignore_ascii_case("h++") + }) +} + +fn args_are_cpp(clang_args: &[Box]) -> bool { + for w in clang_args.windows(2) { + if w[0].as_ref() == "-xc++" || w[1].as_ref() == "-xc++" { + return true; + } + if w[0].as_ref() == "-x" && w[1].as_ref() == "c++" { + return true; + } + if w[0].as_ref() == "-include" && file_is_cpp(w[1].as_ref()) { + return true; + } + } + false +} + +bitflags! { + /// A type used to indicate which kind of items we have to generate. + #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct CodegenConfig: u32 { + /// Whether to generate functions. + const FUNCTIONS = 1 << 0; + /// Whether to generate types. + const TYPES = 1 << 1; + /// Whether to generate constants. + const VARS = 1 << 2; + /// Whether to generate methods. + const METHODS = 1 << 3; + /// Whether to generate constructors + const CONSTRUCTORS = 1 << 4; + /// Whether to generate destructors. + const DESTRUCTORS = 1 << 5; + } +} + +impl CodegenConfig { + /// Returns true if functions should be generated. + pub fn functions(self) -> bool { + self.contains(CodegenConfig::FUNCTIONS) + } + + /// Returns true if types should be generated. + pub fn types(self) -> bool { + self.contains(CodegenConfig::TYPES) + } + + /// Returns true if constants should be generated. + pub fn vars(self) -> bool { + self.contains(CodegenConfig::VARS) + } + + /// Returns true if methods should be generated. + pub fn methods(self) -> bool { + self.contains(CodegenConfig::METHODS) + } + + /// Returns true if constructors should be generated. + pub fn constructors(self) -> bool { + self.contains(CodegenConfig::CONSTRUCTORS) + } + + /// Returns true if destructors should be generated. + pub fn destructors(self) -> bool { + self.contains(CodegenConfig::DESTRUCTORS) + } +} + +impl Default for CodegenConfig { + fn default() -> Self { + CodegenConfig::all() + } +} + +/// Formatting tools that can be used to format the bindings +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum Formatter { + /// Do not format the bindings. + None, + /// Use `rustfmt` to format the bindings. + Rustfmt, + #[cfg(feature = "prettyplease")] + /// Use `prettyplease` to format the bindings. + Prettyplease, +} + +impl Default for Formatter { + fn default() -> Self { + Self::Rustfmt + } +} + +impl FromStr for Formatter { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "none" => Ok(Self::None), + "rustfmt" => Ok(Self::Rustfmt), + #[cfg(feature = "prettyplease")] + "prettyplease" => Ok(Self::Prettyplease), + _ => Err(format!("`{s}` is not a valid formatter")), + } + } +} + +impl std::fmt::Display for Formatter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::None => "none", + Self::Rustfmt => "rustfmt", + #[cfg(feature = "prettyplease")] + Self::Prettyplease => "prettyplease", + }; + + std::fmt::Display::fmt(&s, f) + } +} + +/// Configure and generate Rust bindings for a C/C++ header. +/// +/// This is the main entry point to the library. +/// +/// ```ignore +/// use bindgen::builder; +/// +/// // Configure and generate bindings. +/// let bindings = builder().header("path/to/input/header") +/// .allowlist_type("SomeCoolClass") +/// .allowlist_function("do_some_cool_thing") +/// .generate()?; +/// +/// // Write the generated bindings to an output file. +/// bindings.write_to_file("path/to/output.rs")?; +/// ``` +/// +/// # Enums +/// +/// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on +/// the pattern passed to several methods: +/// +/// 1. [`constified_enum_module()`](#method.constified_enum_module) +/// 2. [`bitfield_enum()`](#method.bitfield_enum) +/// 3. [`newtype_enum()`](#method.newtype_enum) +/// 4. [`rustified_enum()`](#method.rustified_enum) +/// 5. [`rustified_non_exhaustive_enum()`](#method.rustified_non_exhaustive_enum) +/// +/// For each C enum, bindgen tries to match the pattern in the following order: +/// +/// 1. Constified enum module +/// 2. Bitfield enum +/// 3. Newtype enum +/// 4. Rustified enum +/// +/// If none of the above patterns match, then bindgen will generate a set of Rust constants. +/// +/// # Clang arguments +/// +/// Extra arguments can be passed to with clang: +/// 1. [`clang_arg()`](#method.clang_arg): takes a single argument +/// 2. [`clang_args()`](#method.clang_args): takes an iterator of arguments +/// 3. `BINDGEN_EXTRA_CLANG_ARGS` environment variable: whitespace separate +/// environment variable of arguments +/// +/// Clang arguments specific to your crate should be added via the +/// `clang_arg()`/`clang_args()` methods. +/// +/// End-users of the crate may need to set the `BINDGEN_EXTRA_CLANG_ARGS` environment variable to +/// add additional arguments. For example, to build against a different sysroot a user could set +/// `BINDGEN_EXTRA_CLANG_ARGS` to `--sysroot=/path/to/sysroot`. +/// +/// # Regular expression arguments +/// +/// Some [`Builder`] methods, such as `allowlist_*` and `blocklist_*`, allow regular +/// expressions as arguments. These regular expressions will be enclosed in parentheses and +/// anchored with `^` and `$`. So, if the argument passed is ``, the regular expression to be +/// stored will be `^()$`. +/// +/// As a consequence, regular expressions passed to `bindgen` will try to match the whole name of +/// an item instead of a section of it, which means that to match any items with the prefix +/// `prefix`, the `prefix.*` regular expression must be used. +/// +/// Certain methods, like [`Builder::allowlist_function`], use regular expressions over function +/// names. To match C++ methods, prefix the name of the type where they belong, followed by an +/// underscore. So, if the type `Foo` has a method `bar`, it can be matched with the `Foo_bar` +/// regular expression. +/// +/// Additionally, Objective-C interfaces can be matched by prefixing the regular expression with +/// `I`. For example, the `IFoo` regular expression matches the `Foo` interface, and the `IFoo_foo` +/// regular expression matches the `foo` method of the `Foo` interface. +/// +/// Releases of `bindgen` with a version lesser or equal to `0.62.0` used to accept the wildcard +/// pattern `*` as a valid regular expression. This behavior has been deprecated, and the `.*` +/// regular expression must be used instead. +#[derive(Debug, Default, Clone)] +pub struct Builder { + options: BindgenOptions, +} + +/// Construct a new [`Builder`](./struct.Builder.html). +pub fn builder() -> Builder { + Default::default() +} + +fn get_extra_clang_args( + parse_callbacks: &[Rc], +) -> Vec { + // Add any extra arguments from the environment to the clang command line. + let Some(extra_clang_args) = get_target_dependent_env_var( + parse_callbacks, + "BINDGEN_EXTRA_CLANG_ARGS", + ) else { + return vec![]; + }; + + // Try to parse it with shell quoting. If we fail, make it one single big argument. + if let Some(strings) = shlex::split(&extra_clang_args) { + return strings; + } + vec![extra_clang_args] +} + +impl Builder { + /// Generate the Rust bindings using the options built up thus far. + pub fn generate(mut self) -> Result { + // Keep rust_features synced with rust_target + self.options.rust_features = match self.options.rust_edition { + Some(edition) => { + if !edition.is_available(self.options.rust_target) { + return Err(BindgenError::UnsupportedEdition( + edition, + self.options.rust_target, + )); + } + RustFeatures::new(self.options.rust_target, edition) + } + None => { + RustFeatures::new_with_latest_edition(self.options.rust_target) + } + }; + + // Add any extra arguments from the environment to the clang command line. + self.options.clang_args.extend( + get_extra_clang_args(&self.options.parse_callbacks) + .into_iter() + .map(String::into_boxed_str), + ); + + for header in &self.options.input_headers { + self.options + .for_each_callback(|cb| cb.header_file(header.as_ref())); + } + + // Transform input headers to arguments on the clang command line. + self.options.fallback_clang_args = self + .options + .clang_args + .iter() + .filter(|arg| { + !arg.starts_with("-MMD") && + !arg.starts_with("-MD") && + !arg.starts_with("--write-user-dependencies") && + !arg.starts_with("--user-dependencies") + }) + .cloned() + .collect::>(); + self.options.clang_args.extend( + self.options.input_headers + [..self.options.input_headers.len().saturating_sub(1)] + .iter() + .flat_map(|header| ["-include".into(), header.clone()]), + ); + + let input_unsaved_files = + std::mem::take(&mut self.options.input_header_contents) + .into_iter() + .map(|(name, contents)| { + clang::UnsavedFile::new(name.as_ref(), contents.as_ref()) + }) + .collect::>(); + + Bindings::generate(self.options, &input_unsaved_files) + } + + /// Preprocess and dump the input header files to disk. + /// + /// This is useful when debugging bindgen, using C-Reduce, or when filing + /// issues. The resulting file will be named something like `__bindgen.i` or + /// `__bindgen.ii` + pub fn dump_preprocessed_input(&self) -> io::Result<()> { + let clang = + clang_sys::support::Clang::find(None, &[]).ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "Cannot find clang executable", + ) + })?; + + // The contents of a wrapper file that includes all the input header + // files. + let mut wrapper_contents = String::new(); + + // Whether we are working with C or C++ inputs. + let mut is_cpp = args_are_cpp(&self.options.clang_args); + + // For each input header, add `#include "$header"`. + for header in &self.options.input_headers { + is_cpp |= file_is_cpp(header); + + wrapper_contents.push_str("#include \""); + wrapper_contents.push_str(header); + wrapper_contents.push_str("\"\n"); + } + + // For each input header content, add a prefix line of `#line 0 "$name"` + // followed by the contents. + for (name, contents) in &self.options.input_header_contents { + is_cpp |= file_is_cpp(name); + + wrapper_contents.push_str("#line 0 \""); + wrapper_contents.push_str(name); + wrapper_contents.push_str("\"\n"); + wrapper_contents.push_str(contents); + } + + let wrapper_path = PathBuf::from(if is_cpp { + "__bindgen.cpp" + } else { + "__bindgen.c" + }); + + { + let mut wrapper_file = File::create(&wrapper_path)?; + wrapper_file.write_all(wrapper_contents.as_bytes())?; + } + + let mut cmd = Command::new(clang.path); + cmd.arg("-save-temps") + .arg("-E") + .arg("-C") + .arg("-c") + .arg(&wrapper_path) + .stdout(Stdio::piped()); + + for a in &self.options.clang_args { + cmd.arg(a.as_ref()); + } + + for a in get_extra_clang_args(&self.options.parse_callbacks) { + cmd.arg(a); + } + + let mut child = cmd.spawn()?; + + let mut preprocessed = child.stdout.take().unwrap(); + let mut file = File::create(if is_cpp { + "__bindgen.ii" + } else { + "__bindgen.i" + })?; + io::copy(&mut preprocessed, &mut file)?; + + if child.wait()?.success() { + Ok(()) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "clang exited with non-zero status", + )) + } + } +} + +impl BindgenOptions { + fn build(&mut self) { + const REGEX_SETS_LEN: usize = 29; + + let regex_sets: [_; REGEX_SETS_LEN] = [ + &mut self.blocklisted_types, + &mut self.blocklisted_functions, + &mut self.blocklisted_items, + &mut self.blocklisted_files, + &mut self.blocklisted_vars, + &mut self.opaque_types, + &mut self.allowlisted_vars, + &mut self.allowlisted_types, + &mut self.allowlisted_functions, + &mut self.allowlisted_files, + &mut self.allowlisted_items, + &mut self.bitfield_enums, + &mut self.constified_enums, + &mut self.constified_enum_modules, + &mut self.newtype_enums, + &mut self.newtype_global_enums, + &mut self.rustified_enums, + &mut self.rustified_non_exhaustive_enums, + &mut self.type_alias, + &mut self.new_type_alias, + &mut self.new_type_alias_deref, + &mut self.bindgen_wrapper_union, + &mut self.manually_drop_union, + &mut self.no_partialeq_types, + &mut self.no_copy_types, + &mut self.no_debug_types, + &mut self.no_default_types, + &mut self.no_hash_types, + &mut self.must_use_types, + ]; + + let record_matches = self.record_matches; + #[cfg(feature = "experimental")] + { + let sets_len = REGEX_SETS_LEN + self.abi_overrides.len(); + let names = if self.emit_diagnostics { + <[&str; REGEX_SETS_LEN]>::into_iter([ + "--blocklist-type", + "--blocklist-function", + "--blocklist-item", + "--blocklist-file", + "--blocklist-var", + "--opaque-type", + "--allowlist-type", + "--allowlist-function", + "--allowlist-var", + "--allowlist-file", + "--allowlist-item", + "--bitfield-enum", + "--newtype-enum", + "--newtype-global-enum", + "--rustified-enum", + "--rustified-enum-non-exhaustive", + "--constified-enum-module", + "--constified-enum", + "--type-alias", + "--new-type-alias", + "--new-type-alias-deref", + "--bindgen-wrapper-union", + "--manually-drop-union", + "--no-partialeq", + "--no-copy", + "--no-debug", + "--no-default", + "--no-hash", + "--must-use", + ]) + .chain((0..self.abi_overrides.len()).map(|_| "--override-abi")) + .map(Some) + .collect() + } else { + vec![None; sets_len] + }; + + for (regex_set, name) in + self.abi_overrides.values_mut().chain(regex_sets).zip(names) + { + regex_set.build_with_diagnostics(record_matches, name); + } + } + #[cfg(not(feature = "experimental"))] + for regex_set in self.abi_overrides.values_mut().chain(regex_sets) { + regex_set.build(record_matches); + } + } + + /// Update rust target version + pub fn set_rust_target(&mut self, rust_target: RustTarget) { + self.rust_target = rust_target; + } + + /// Get features supported by target Rust version + pub fn rust_features(&self) -> RustFeatures { + self.rust_features + } + + fn last_callback( + &self, + f: impl Fn(&dyn callbacks::ParseCallbacks) -> Option, + ) -> Option { + self.parse_callbacks + .iter() + .filter_map(|cb| f(cb.as_ref())) + .next_back() + } + + fn all_callbacks( + &self, + f: impl Fn(&dyn callbacks::ParseCallbacks) -> Vec, + ) -> Vec { + self.parse_callbacks + .iter() + .flat_map(|cb| f(cb.as_ref())) + .collect() + } + + fn for_each_callback(&self, f: impl Fn(&dyn callbacks::ParseCallbacks)) { + self.parse_callbacks.iter().for_each(|cb| f(cb.as_ref())); + } + + fn process_comment(&self, comment: &str) -> String { + let comment = comment::preprocess(comment); + self.last_callback(|cb| cb.process_comment(&comment)) + .unwrap_or(comment) + } +} + +#[cfg(feature = "runtime")] +fn ensure_libclang_is_loaded() { + use std::sync::{Arc, OnceLock}; + + if clang_sys::is_loaded() { + return; + } + + // XXX (issue #350): Ensure that our dynamically loaded `libclang` + // doesn't get dropped prematurely, nor is loaded multiple times + // across different threads. + + static LIBCLANG: OnceLock> = OnceLock::new(); + let libclang = LIBCLANG.get_or_init(|| { + clang_sys::load().expect("Unable to find libclang"); + clang_sys::get_library() + .expect("We just loaded libclang and it had better still be here!") + }); + + clang_sys::set_library(Some(libclang.clone())); +} + +#[cfg(not(feature = "runtime"))] +fn ensure_libclang_is_loaded() {} + +/// Error type for rust-bindgen. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum BindgenError { + /// The header was a folder. + FolderAsHeader(PathBuf), + /// Permissions to read the header is insufficient. + InsufficientPermissions(PathBuf), + /// The header does not exist. + NotExist(PathBuf), + /// Clang diagnosed an error. + ClangDiagnostic(String), + /// Code generation reported an error. + Codegen(CodegenError), + /// The passed edition is not available on that Rust target. + UnsupportedEdition(RustEdition, RustTarget), +} + +impl std::fmt::Display for BindgenError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BindgenError::FolderAsHeader(h) => { + write!(f, "'{}' is a folder", h.display()) + } + BindgenError::InsufficientPermissions(h) => { + write!(f, "insufficient permissions to read '{}'", h.display()) + } + BindgenError::NotExist(h) => { + write!(f, "header '{}' does not exist.", h.display()) + } + BindgenError::ClangDiagnostic(message) => { + write!(f, "clang diagnosed error: {message}") + } + BindgenError::Codegen(err) => { + write!(f, "codegen error: {err}") + } + BindgenError::UnsupportedEdition(edition, target) => { + write!(f, "edition {edition} is not available on Rust {target}") + } + } + } +} + +impl std::error::Error for BindgenError {} + +/// Generated Rust bindings. +#[derive(Debug)] +pub struct Bindings { + options: BindgenOptions, + module: proc_macro2::TokenStream, +} + +pub(crate) const HOST_TARGET: &str = + include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); + +// Some architecture triplets are different between rust and libclang, see #1211 +// and duplicates. +fn rust_to_clang_target(rust_target: &str) -> Box { + const TRIPLE_HYPHENS_MESSAGE: &str = "Target triple should contain hyphens"; + + let mut triple: Vec<&str> = rust_target.split_terminator('-').collect(); + + assert!(!triple.is_empty(), "{TRIPLE_HYPHENS_MESSAGE}"); + triple.resize(4, ""); + + // RISC-V + if triple[0].starts_with("riscv32") { + triple[0] = "riscv32"; + } else if triple[0].starts_with("riscv64") { + triple[0] = "riscv64"; + } + + // Apple + if triple[1] == "apple" { + if triple[0] == "aarch64" { + triple[0] = "arm64"; + } + if triple[3] == "sim" { + triple[3] = "simulator"; + } + } + + // ESP-IDF + if triple[2] == "espidf" { + triple[2] = "elf"; + } + + triple + .iter() + .skip(1) + .fold(triple[0].to_string(), |triple, part| { + if part.is_empty() { + triple + } else { + triple + "-" + part + } + }) + .into() +} + +/// Returns the effective target, and whether it was explicitly specified on the +/// clang flags. +fn find_effective_target(clang_args: &[Box]) -> (Box, bool) { + let mut args = clang_args.iter(); + while let Some(opt) = args.next() { + if opt.starts_with("--target=") { + let mut split = opt.split('='); + split.next(); + return (split.next().unwrap().into(), true); + } + + if opt.as_ref() == "-target" { + if let Some(target) = args.next() { + return (target.clone(), true); + } + } + } + + // If we're running from a build script, try to find the cargo target. + if let Ok(t) = env::var("TARGET") { + return (rust_to_clang_target(&t), false); + } + + (rust_to_clang_target(HOST_TARGET), false) +} + +impl Bindings { + /// Generate bindings for the given options. + pub(crate) fn generate( + mut options: BindgenOptions, + input_unsaved_files: &[clang::UnsavedFile], + ) -> Result { + ensure_libclang_is_loaded(); + + #[cfg(feature = "runtime")] + match clang_sys::get_library().unwrap().version() { + None => { + warn!("Could not detect a Clang version, make sure you are using libclang 9 or newer"); + } + Some(version) => { + if version < clang_sys::Version::V9_0 { + warn!("Detected Clang version {version:?} which is unsupported and can cause invalid code generation, use libclang 9 or newer"); + } + } + } + + #[cfg(feature = "runtime")] + debug!( + "Generating bindings, libclang at {}", + clang_sys::get_library().unwrap().path().display() + ); + #[cfg(not(feature = "runtime"))] + debug!("Generating bindings, libclang linked"); + + options.build(); + + let (effective_target, explicit_target) = + find_effective_target(&options.clang_args); + + let is_host_build = + rust_to_clang_target(HOST_TARGET) == effective_target; + + // NOTE: The is_host_build check wouldn't be sound normally in some + // cases if we were to call a binary (if you have a 32-bit clang and are + // building on a 64-bit system for example). But since we rely on + // opening libclang.so, it has to be the same architecture and thus the + // check is fine. + if !explicit_target && !is_host_build { + options.clang_args.insert( + 0, + format!("--target={effective_target}").into_boxed_str(), + ); + } + + fn detect_include_paths(options: &mut BindgenOptions) { + if !options.detect_include_paths { + return; + } + + // Filter out include paths and similar stuff, so we don't incorrectly + // promote them to `-isystem`. + let clang_args_for_clang_sys = { + let mut last_was_include_prefix = false; + options + .clang_args + .iter() + .filter(|arg| { + if last_was_include_prefix { + last_was_include_prefix = false; + return false; + } + + let arg = arg.as_ref(); + + // https://clang.llvm.org/docs/ClangCommandLineReference.html + // -isystem and -isystem-after are harmless. + if arg == "-I" || arg == "--include-directory" { + last_was_include_prefix = true; + return false; + } + + if arg.starts_with("-I") || + arg.starts_with("--include-directory=") + { + return false; + } + + true + }) + .map(|arg| arg.clone().into()) + .collect::>() + }; + + debug!( + "Trying to find clang with flags: {clang_args_for_clang_sys:?}" + ); + + let Some(clang) = clang_sys::support::Clang::find( + None, + &clang_args_for_clang_sys, + ) else { + return; + }; + + debug!("Found clang: {clang:?}"); + + // Whether we are working with C or C++ inputs. + let is_cpp = args_are_cpp(&options.clang_args) || + options.input_headers.iter().any(|h| file_is_cpp(h)); + + let search_paths = if is_cpp { + clang.cpp_search_paths + } else { + clang.c_search_paths + }; + + if let Some(search_paths) = search_paths { + for path in search_paths { + if let Ok(path) = path.into_os_string().into_string() { + options.clang_args.push("-isystem".into()); + options.clang_args.push(path.into_boxed_str()); + } + } + } + } + + detect_include_paths(&mut options); + + #[cfg(unix)] + fn can_read(perms: &std::fs::Permissions) -> bool { + use std::os::unix::fs::PermissionsExt; + perms.mode() & 0o444 > 0 + } + + #[cfg(not(unix))] + fn can_read(_: &std::fs::Permissions) -> bool { + true + } + + if let Some(h) = options.input_headers.last() { + let path = Path::new(h.as_ref()); + if let Ok(md) = std::fs::metadata(path) { + if md.is_dir() { + return Err(BindgenError::FolderAsHeader(path.into())); + } + if !can_read(&md.permissions()) { + return Err(BindgenError::InsufficientPermissions( + path.into(), + )); + } + options.clang_args.push(h.clone()); + } else { + return Err(BindgenError::NotExist(path.into())); + } + } + + for (idx, f) in input_unsaved_files.iter().enumerate() { + if idx != 0 || !options.input_headers.is_empty() { + options.clang_args.push("-include".into()); + } + options.clang_args.push(f.name.to_str().unwrap().into()); + } + + debug!("Fixed-up options: {options:?}"); + + let time_phases = options.time_phases; + let mut context = BindgenContext::new(options, input_unsaved_files); + + if is_host_build { + debug_assert_eq!( + context.target_pointer_size(), + size_of::<*mut ()>(), + "{effective_target:?} {HOST_TARGET:?}" + ); + } + + { + let _t = time::Timer::new("parse").with_output(time_phases); + parse(&mut context)?; + } + + let (module, options) = + codegen::codegen(context).map_err(BindgenError::Codegen)?; + + Ok(Bindings { options, module }) + } + + /// Write these bindings as source text to a file. + pub fn write_to_file>(&self, path: P) -> io::Result<()> { + let file = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path.as_ref())?; + self.write(Box::new(file))?; + Ok(()) + } + + /// Write these bindings as source text to the given `Write`able. + pub fn write<'a>(&self, mut writer: Box) -> io::Result<()> { + const NL: &str = if cfg!(windows) { "\r\n" } else { "\n" }; + + if !self.options.disable_header_comment { + let version = + option_env!("CARGO_PKG_VERSION").unwrap_or("(unknown version)"); + write!( + writer, + "/* automatically generated by rust-bindgen {version} */{NL}{NL}", + )?; + } + + for line in &self.options.raw_lines { + writer.write_all(line.as_bytes())?; + writer.write_all(NL.as_bytes())?; + } + + if !self.options.raw_lines.is_empty() { + writer.write_all(NL.as_bytes())?; + } + + match self.format_tokens(&self.module) { + Ok(formatted_bindings) => { + writer.write_all(formatted_bindings.as_bytes())?; + } + Err(err) => { + eprintln!( + "Failed to run rustfmt: {err} (non-fatal, continuing)" + ); + writer.write_all(self.module.to_string().as_bytes())?; + } + } + Ok(()) + } + + /// Gets the rustfmt path to rustfmt the generated bindings. + fn rustfmt_path(&self) -> Cow<'_, Path> { + debug_assert!(matches!(self.options.formatter, Formatter::Rustfmt)); + if let Some(ref p) = self.options.rustfmt_path { + Cow::Borrowed(p) + } else if let Ok(rustfmt) = env::var("RUSTFMT") { + Cow::Owned(rustfmt.into()) + } else { + // No rustfmt binary was specified, so assume that the binary is called + // "rustfmt" and that it is in the user's PATH. + Cow::Borrowed(Path::new("rustfmt")) + } + } + + /// Formats a token stream with the formatter set up in `BindgenOptions`. + fn format_tokens( + &self, + tokens: &proc_macro2::TokenStream, + ) -> io::Result { + let _t = time::Timer::new("rustfmt_generated_string") + .with_output(self.options.time_phases); + + match self.options.formatter { + Formatter::None => return Ok(tokens.to_string()), + #[cfg(feature = "prettyplease")] + Formatter::Prettyplease => { + return Ok(prettyplease::unparse(&syn::parse_quote!(#tokens))); + } + Formatter::Rustfmt => (), + } + + let rustfmt = self.rustfmt_path(); + let mut cmd = Command::new(&*rustfmt); + + cmd.stdin(Stdio::piped()).stdout(Stdio::piped()); + + if let Some(path) = self + .options + .rustfmt_configuration_file + .as_ref() + .and_then(|f| f.to_str()) + { + cmd.args(["--config-path", path]); + } + + let edition = self + .options + .rust_edition + .unwrap_or_else(|| self.options.rust_target.latest_edition()); + cmd.args(["--edition", &format!("{edition}")]); + + let mut child = cmd.spawn()?; + let mut child_stdin = child.stdin.take().unwrap(); + let mut child_stdout = child.stdout.take().unwrap(); + + let source = tokens.to_string(); + + // Write to stdin in a new thread, so that we can read from stdout on this + // thread. This keeps the child from blocking on writing to its stdout which + // might block us from writing to its stdin. + let stdin_handle = ::std::thread::spawn(move || { + let _ = child_stdin.write_all(source.as_bytes()); + source + }); + + let mut output = vec![]; + io::copy(&mut child_stdout, &mut output)?; + + let status = child.wait()?; + let source = stdin_handle.join().expect( + "The thread writing to rustfmt's stdin doesn't do \ + anything that could panic", + ); + + match String::from_utf8(output) { + Ok(bindings) => match status.code() { + Some(0) => Ok(bindings), + Some(2) => Err(io::Error::new( + io::ErrorKind::Other, + "Rustfmt parsing errors.".to_string(), + )), + Some(3) => { + rustfmt_non_fatal_error_diagnostic( + "Rustfmt could not format some lines", + &self.options, + ); + Ok(bindings) + } + _ => Err(io::Error::new( + io::ErrorKind::Other, + "Internal rustfmt error".to_string(), + )), + }, + _ => Ok(source), + } + } +} + +fn rustfmt_non_fatal_error_diagnostic(msg: &str, _options: &BindgenOptions) { + warn!("{msg}"); + + #[cfg(feature = "experimental")] + if _options.emit_diagnostics { + use crate::diagnostics::{Diagnostic, Level}; + + Diagnostic::default() + .with_title(msg, Level::Warning) + .add_annotation( + "The bindings will be generated but not formatted.", + Level::Note, + ) + .display(); + } +} + +impl std::fmt::Display for Bindings { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut bytes = vec![]; + self.write(Box::new(&mut bytes) as Box) + .expect("writing to a vec cannot fail"); + f.write_str( + std::str::from_utf8(&bytes) + .expect("we should only write bindings that are valid utf-8"), + ) + } +} + +/// Determines whether the given cursor is in any of the files matched by the +/// options. +fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool { + ctx.options().builtins || !cursor.is_builtin() +} + +/// Parse one `Item` from the Clang cursor. +fn parse_one( + ctx: &mut BindgenContext, + cursor: clang::Cursor, + parent: Option, +) { + if !filter_builtins(ctx, &cursor) { + return; + } + + match Item::parse(cursor, parent, ctx) { + Ok(..) => {} + Err(ParseError::Continue) => {} + Err(ParseError::Recurse) => { + cursor + .visit_sorted(ctx, |ctx, child| parse_one(ctx, child, parent)); + } + } +} + +/// Parse the Clang AST into our `Item` internal representation. +fn parse(context: &mut BindgenContext) -> Result<(), BindgenError> { + use clang_sys::*; + + let mut error = None; + for d in &context.translation_unit().diags() { + let msg = d.format(); + let is_err = d.severity() >= CXDiagnostic_Error; + if is_err { + let error = error.get_or_insert_with(String::new); + error.push_str(&msg); + error.push('\n'); + } else { + eprintln!("clang diag: {msg}"); + } + } + + if let Some(message) = error { + return Err(BindgenError::ClangDiagnostic(message)); + } + + let cursor = context.translation_unit().cursor(); + + if context.options().emit_ast { + fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult { + if cur.is_builtin() { + CXChildVisit_Continue + } else { + clang::ast_dump(cur, 0) + } + } + cursor.visit(|cur| dump_if_not_builtin(&cur)); + } + + let root = context.root_module(); + context.with_module(root, |ctx| { + cursor.visit_sorted(ctx, |ctx, child| parse_one(ctx, child, None)); + }); + + assert_eq!( + context.current_module(), + context.root_module(), + "How did this happen?" + ); + Ok(()) +} + +/// Extracted Clang version data +#[derive(Debug)] +pub struct ClangVersion { + /// Major and minor semver, if parsing was successful + pub parsed: Option<(u32, u32)>, + /// full version string + pub full: String, +} + +/// Get the major and the minor semver numbers of Clang's version +pub fn clang_version() -> ClangVersion { + ensure_libclang_is_loaded(); + + //Debian clang version 11.0.1-2 + let raw_v: String = clang::extract_clang_version(); + let split_v: Option> = raw_v + .split_whitespace() + .find(|t| t.chars().next().is_some_and(|v| v.is_ascii_digit())) + .map(|v| v.split('.').collect()); + if let Some(v) = split_v { + if v.len() >= 2 { + let maybe_major = v[0].parse::(); + let maybe_minor = v[1].parse::(); + if let (Ok(major), Ok(minor)) = (maybe_major, maybe_minor) { + return ClangVersion { + parsed: Some((major, minor)), + full: raw_v.clone(), + }; + } + } + } + ClangVersion { + parsed: None, + full: raw_v.clone(), + } +} + +fn env_var + AsRef>( + parse_callbacks: &[Rc], + key: K, +) -> Result { + for callback in parse_callbacks { + callback.read_env_var(key.as_ref()); + } + env::var(key) +} + +/// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found. +fn get_target_dependent_env_var( + parse_callbacks: &[Rc], + var: &str, +) -> Option { + if let Ok(target) = env_var(parse_callbacks, "TARGET") { + if let Ok(v) = env_var(parse_callbacks, format!("{var}_{target}")) { + return Some(v); + } + if let Ok(v) = env_var( + parse_callbacks, + format!("{var}_{}", target.replace('-', "_")), + ) { + return Some(v); + } + } + + env_var(parse_callbacks, var).ok() +} + +/// A `ParseCallbacks` implementation that will act on file includes by echoing a rerun-if-changed +/// line and on env variable usage by echoing a rerun-if-env-changed line +/// +/// When running inside a `build.rs` script, this can be used to make cargo invalidate the +/// generated bindings whenever any of the files included from the header change: +/// ``` +/// use bindgen::builder; +/// let bindings = builder() +/// .header("path/to/input/header") +/// .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) +/// .generate(); +/// ``` +#[derive(Debug)] +pub struct CargoCallbacks { + rerun_on_header_files: bool, +} + +/// Create a new `CargoCallbacks` value with [`CargoCallbacks::rerun_on_header_files`] disabled. +/// +/// This constructor has been deprecated in favor of [`CargoCallbacks::new`] where +/// [`CargoCallbacks::rerun_on_header_files`] is enabled by default. +#[deprecated = "Use `CargoCallbacks::new()` instead. Please, check the documentation for further information."] +pub const CargoCallbacks: CargoCallbacks = CargoCallbacks { + rerun_on_header_files: false, +}; + +impl CargoCallbacks { + /// Create a new `CargoCallbacks` value. + pub fn new() -> Self { + Self { + rerun_on_header_files: true, + } + } + + /// Whether Cargo should re-run the build script if any of the input header files has changed. + /// + /// This option is enabled by default unless the deprecated [`const@CargoCallbacks`] + /// constructor is used. + pub fn rerun_on_header_files(mut self, doit: bool) -> Self { + self.rerun_on_header_files = doit; + self + } +} + +impl Default for CargoCallbacks { + fn default() -> Self { + Self::new() + } +} + +impl callbacks::ParseCallbacks for CargoCallbacks { + fn header_file(&self, filename: &str) { + if self.rerun_on_header_files { + println!("cargo:rerun-if-changed={filename}"); + } + } + + fn include_file(&self, filename: &str) { + println!("cargo:rerun-if-changed={filename}"); + } + + fn read_env_var(&self, key: &str) { + println!("cargo:rerun-if-env-changed={key}"); + } +} + +/// Test `command_line_flag` function. +#[test] +fn commandline_flag_unit_test_function() { + //Test 1 + let bindings = builder(); + let command_line_flags = bindings.command_line_flags(); + + let test_cases = [ + "--rust-target", + "--no-derive-default", + "--generate", + "functions,types,vars,methods,constructors,destructors", + ] + .iter() + .map(|&x| x.into()) + .collect::>(); + + assert!(test_cases.iter().all(|x| command_line_flags.contains(x))); + + //Test 2 + let bindings = builder() + .header("input_header") + .allowlist_type("Distinct_Type") + .allowlist_function("safe_function"); + + let command_line_flags = bindings.command_line_flags(); + let test_cases = [ + "--rust-target", + "input_header", + "--no-derive-default", + "--generate", + "functions,types,vars,methods,constructors,destructors", + "--allowlist-type", + "Distinct_Type", + "--allowlist-function", + "safe_function", + ] + .iter() + .map(|&x| x.into()) + .collect::>(); + println!("{command_line_flags:?}"); + + assert!(test_cases.iter().all(|x| command_line_flags.contains(x))); +} + +#[test] +fn test_rust_to_clang_target() { + assert_eq!( + rust_to_clang_target("aarch64-apple-ios").as_ref(), + "arm64-apple-ios" + ); +} + +#[test] +fn test_rust_to_clang_target_riscv() { + assert_eq!( + rust_to_clang_target("riscv64gc-unknown-linux-gnu").as_ref(), + "riscv64-unknown-linux-gnu" + ); + assert_eq!( + rust_to_clang_target("riscv64imac-unknown-none-elf").as_ref(), + "riscv64-unknown-none-elf" + ); + assert_eq!( + rust_to_clang_target("riscv32imc-unknown-none-elf").as_ref(), + "riscv32-unknown-none-elf" + ); + assert_eq!( + rust_to_clang_target("riscv32imac-unknown-none-elf").as_ref(), + "riscv32-unknown-none-elf" + ); + assert_eq!( + rust_to_clang_target("riscv32imafc-unknown-none-elf").as_ref(), + "riscv32-unknown-none-elf" + ); + assert_eq!( + rust_to_clang_target("riscv32i-unknown-none-elf").as_ref(), + "riscv32-unknown-none-elf" + ); +} + +#[test] +fn test_rust_to_clang_target_espidf() { + assert_eq!( + rust_to_clang_target("riscv32imc-esp-espidf").as_ref(), + "riscv32-esp-elf" + ); + assert_eq!( + rust_to_clang_target("xtensa-esp32-espidf").as_ref(), + "xtensa-esp32-elf" + ); +} + +#[test] +fn test_rust_to_clang_target_simulator() { + assert_eq!( + rust_to_clang_target("aarch64-apple-ios-sim").as_ref(), + "arm64-apple-ios-simulator" + ); + assert_eq!( + rust_to_clang_target("aarch64-apple-tvos-sim").as_ref(), + "arm64-apple-tvos-simulator" + ); + assert_eq!( + rust_to_clang_target("aarch64-apple-watchos-sim").as_ref(), + "arm64-apple-watchos-simulator" + ); +} diff --git a/bindgen/log_stubs.rs b/bindgen/log_stubs.rs new file mode 100644 index 0000000000..51d2f81fd1 --- /dev/null +++ b/bindgen/log_stubs.rs @@ -0,0 +1,38 @@ +#![allow(unused)] + +#[clippy::format_args] +macro_rules! log { + (target: $target:expr, $lvl:expr, $($arg:tt)+) => {{ + let _ = $target; + let _ = log!($lvl, $($arg)+); + }}; + ($lvl:expr, $($arg:tt)+) => {{ + let _ = $lvl; + let _ = format_args!($($arg)+); + }}; +} +#[clippy::format_args] +macro_rules! error { + (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) }; + ($($arg:tt)+) => { log!("", $($arg)+) }; +} +#[clippy::format_args] +macro_rules! warn { + (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*) }; + ($($arg:tt)*) => { log!("", $($arg)*) }; +} +#[clippy::format_args] +macro_rules! info { + (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) }; + ($($arg:tt)+) => { log!("", $($arg)+) }; +} +#[clippy::format_args] +macro_rules! debug { + (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) }; + ($($arg:tt)+) => { log!("", $($arg)+) }; +} +#[clippy::format_args] +macro_rules! trace { + (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) }; + ($($arg:tt)+) => { log!("", $($arg)+) }; +} diff --git a/bindgen/options/as_args.rs b/bindgen/options/as_args.rs new file mode 100644 index 0000000000..83103fdaf4 --- /dev/null +++ b/bindgen/options/as_args.rs @@ -0,0 +1,52 @@ +use std::path::PathBuf; + +use crate::regex_set::RegexSet; + +/// Trait used to turn [`crate::BindgenOptions`] fields into CLI args. +pub(super) trait AsArgs { + fn as_args(&self, args: &mut Vec, flag: &str); +} + +/// If the `bool` is `true`, `flag` is pushed into `args`. +/// +/// be careful about the truth value of the field as some options, like `--no-layout-tests`, are +/// actually negations of the fields. +impl AsArgs for bool { + fn as_args(&self, args: &mut Vec, flag: &str) { + if *self { + args.push(flag.to_string()); + } + } +} + +/// Iterate over all the items of the `RegexSet` and push `flag` followed by the item into `args` +/// for each item. +impl AsArgs for RegexSet { + fn as_args(&self, args: &mut Vec, flag: &str) { + for item in self.get_items() { + args.extend_from_slice(&[flag.to_owned(), item.clone().into()]); + } + } +} + +/// If the `Option` is `Some(value)`, push `flag` followed by `value`. +impl AsArgs for Option { + fn as_args(&self, args: &mut Vec, flag: &str) { + if let Some(string) = self { + args.extend_from_slice(&[flag.to_owned(), string.clone()]); + } + } +} + +/// If the `Option` is `Some(path)`, push `flag` followed by the [`std::path::Path::display`] +/// representation of `path`. +impl AsArgs for Option { + fn as_args(&self, args: &mut Vec, flag: &str) { + if let Some(path) = self { + args.extend_from_slice(&[ + flag.to_owned(), + path.display().to_string(), + ]); + } + } +} diff --git a/bindgen/options/cli.rs b/bindgen/options/cli.rs new file mode 100644 index 0000000000..972b487c25 --- /dev/null +++ b/bindgen/options/cli.rs @@ -0,0 +1,1161 @@ +#![allow(unused_qualifications)] // Clap somehow generates a lot of these + +use crate::{ + builder, + callbacks::{ + AttributeInfo, DeriveInfo, ItemInfo, ParseCallbacks, TypeKind, + }, + features::{RustEdition, EARLIEST_STABLE_RUST}, + regex_set::RegexSet, + Abi, AliasVariation, Builder, CodegenConfig, EnumVariation, + FieldVisibilityKind, Formatter, MacroTypeVariation, NonCopyUnionStyle, + RustTarget, +}; +use clap::{ + error::{Error, ErrorKind}, + CommandFactory, Parser, +}; +use proc_macro2::TokenStream; +use std::io; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::{fs::File, process::exit}; + +fn rust_target_help() -> String { + format!( + "Version of the Rust compiler to target. Any Rust version after {EARLIEST_STABLE_RUST} is supported. Defaults to {}.", + RustTarget::default() + ) +} + +fn rust_edition_help() -> String { + format!("Rust edition to target. Defaults to the latest edition supported by the chosen Rust target. Possible values: ({}). ", RustEdition::ALL.map(|e| e.to_string()).join("|")) +} + +fn parse_codegen_config( + what_to_generate: &str, +) -> Result { + let mut config = CodegenConfig::empty(); + for what in what_to_generate.split(',') { + match what { + "functions" => config.insert(CodegenConfig::FUNCTIONS), + "types" => config.insert(CodegenConfig::TYPES), + "vars" => config.insert(CodegenConfig::VARS), + "methods" => config.insert(CodegenConfig::METHODS), + "constructors" => config.insert(CodegenConfig::CONSTRUCTORS), + "destructors" => config.insert(CodegenConfig::DESTRUCTORS), + otherwise => { + return Err(Error::raw( + ErrorKind::InvalidValue, + format!("Unknown codegen item kind: {otherwise}"), + )); + } + } + } + + Ok(config) +} + +fn parse_rustfmt_config_path(path_str: &str) -> Result { + let path = Path::new(path_str); + + if !path.is_absolute() { + return Err(Error::raw( + ErrorKind::InvalidValue, + "--rustfmt-configuration-file needs to be an absolute path!", + )); + } + + if path.to_str().is_none() { + return Err(Error::raw( + ErrorKind::InvalidUtf8, + "--rustfmt-configuration-file contains non-valid UTF8 characters.", + )); + } + + Ok(path.to_path_buf()) +} + +fn parse_abi_override(abi_override: &str) -> Result<(Abi, String), Error> { + let (regex, abi_str) = abi_override + .rsplit_once('=') + .ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?; + + let abi = abi_str + .parse() + .map_err(|err| Error::raw(ErrorKind::InvalidValue, err))?; + + Ok((abi, regex.to_owned())) +} + +fn parse_custom_derive( + custom_derive: &str, +) -> Result<(Vec, String), Error> { + let (regex, derives) = custom_derive + .rsplit_once('=') + .ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?; + + let derives = derives.split(',').map(|s| s.to_owned()).collect(); + + Ok((derives, regex.to_owned())) +} + +fn parse_custom_attribute( + custom_attribute: &str, +) -> Result<(Vec, String), Error> { + let mut brace_level = 0; + let (regex, attributes) = custom_attribute + .rsplit_once(|c| { + match c { + ']' => brace_level += 1, + '[' => brace_level -= 1, + _ => {} + } + c == '=' && brace_level == 0 + }) + .ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?; + + let mut brace_level = 0; + let attributes = attributes + .split(|c| { + match c { + ']' => brace_level += 1, + '[' => brace_level -= 1, + _ => {} + } + c == ',' && brace_level == 0 + }) + .map(|s| s.to_owned()) + .collect::>(); + + for attribute in &attributes { + if let Err(err) = TokenStream::from_str(attribute) { + return Err(Error::raw(ErrorKind::InvalidValue, err)); + } + } + + Ok((attributes, regex.to_owned())) +} + +#[derive(Parser, Debug)] +#[clap( + about = "Generates Rust bindings from C/C++ headers.", + override_usage = "bindgen
-- ...", + trailing_var_arg = true +)] +#[allow(clippy::doc_markdown)] +struct BindgenCommand { + /// C or C++ header file. + header: Option, + /// Path to write depfile to. + #[arg(long)] + depfile: Option, + /// The default STYLE of code used to generate enums. + #[arg(long, value_name = "STYLE")] + default_enum_style: Option, + /// Mark any enum whose name matches REGEX as a set of bitfield flags. + #[arg(long, value_name = "REGEX")] + bitfield_enum: Vec, + /// Mark any enum whose name matches REGEX as a newtype. + #[arg(long, value_name = "REGEX")] + newtype_enum: Vec, + /// Mark any enum whose name matches REGEX as a global newtype. + #[arg(long, value_name = "REGEX")] + newtype_global_enum: Vec, + /// Mark any enum whose name matches REGEX as a Rust enum. + #[arg(long, value_name = "REGEX")] + rustified_enum: Vec, + /// Mark any enum whose name matches REGEX as a non-exhaustive Rust enum. + #[arg(long, value_name = "REGEX")] + rustified_non_exhaustive_enum: Vec, + /// Mark any enum whose name matches REGEX as a series of constants. + #[arg(long, value_name = "REGEX")] + constified_enum: Vec, + /// Mark any enum whose name matches REGEX as a module of constants. + #[arg(long, value_name = "REGEX")] + constified_enum_module: Vec, + /// The default signed/unsigned TYPE for C macro constants. + #[arg(long, value_name = "TYPE")] + default_macro_constant_type: Option, + /// The default STYLE of code used to generate typedefs. + #[arg(long, value_name = "STYLE")] + default_alias_style: Option, + /// Mark any typedef alias whose name matches REGEX to use normal type aliasing. + #[arg(long, value_name = "REGEX")] + normal_alias: Vec, + /// Mark any typedef alias whose name matches REGEX to have a new type generated for it. + #[arg(long, value_name = "REGEX")] + new_type_alias: Vec, + /// Mark any typedef alias whose name matches REGEX to have a new type with Deref and DerefMut to the inner type. + #[arg(long, value_name = "REGEX")] + new_type_alias_deref: Vec, + /// The default STYLE of code used to generate unions with non-Copy members. Note that ManuallyDrop was first stabilized in Rust 1.20.0. + #[arg(long, value_name = "STYLE")] + default_non_copy_union_style: Option, + /// Mark any union whose name matches REGEX and who has a non-Copy member to use a bindgen-generated wrapper for fields. + #[arg(long, value_name = "REGEX")] + bindgen_wrapper_union: Vec, + /// Mark any union whose name matches REGEX and who has a non-Copy member to use ManuallyDrop (stabilized in Rust 1.20.0) for fields. + #[arg(long, value_name = "REGEX")] + manually_drop_union: Vec, + /// Mark TYPE as hidden. + #[arg(long, value_name = "TYPE")] + blocklist_type: Vec, + /// Mark FUNCTION as hidden. + #[arg(long, value_name = "FUNCTION")] + blocklist_function: Vec, + /// Mark ITEM as hidden. + #[arg(long, value_name = "ITEM")] + blocklist_item: Vec, + /// Mark FILE as hidden. + #[arg(long, value_name = "FILE")] + blocklist_file: Vec, + /// Mark VAR as hidden. + #[arg(long, value_name = "VAR")] + blocklist_var: Vec, + /// Avoid generating layout tests for any type. + #[arg(long)] + no_layout_tests: bool, + /// Avoid deriving Copy on any type. + #[arg(long)] + no_derive_copy: bool, + /// Avoid deriving Debug on any type. + #[arg(long)] + no_derive_debug: bool, + /// Avoid deriving Default on any type. + #[arg(long, hide = true)] + no_derive_default: bool, + /// Create a Debug implementation if it cannot be derived automatically. + #[arg(long)] + impl_debug: bool, + /// Create a PartialEq implementation if it cannot be derived automatically. + #[arg(long)] + impl_partialeq: bool, + /// Derive Default on any type. + #[arg(long)] + with_derive_default: bool, + /// Derive Hash on any type. + #[arg(long)] + with_derive_hash: bool, + /// Derive PartialEq on any type. + #[arg(long)] + with_derive_partialeq: bool, + /// Derive PartialOrd on any type. + #[arg(long)] + with_derive_partialord: bool, + /// Derive Eq on any type. + #[arg(long)] + with_derive_eq: bool, + /// Derive Ord on any type. + #[arg(long)] + with_derive_ord: bool, + /// Avoid including doc comments in the output, see: + #[arg(long)] + no_doc_comments: bool, + /// Disable allowlisting types recursively. This will cause bindgen to emit Rust code that won't compile! See the `bindgen::Builder::allowlist_recursively` method's documentation for details. + #[arg(long)] + no_recursive_allowlist: bool, + /// Use extern crate instead of use for objc. + #[arg(long)] + objc_extern_crate: bool, + /// Use `NonNull` in place of raw pointers for C++ references. + #[arg(long)] + nonnull_references: bool, + /// Generate block signatures instead of void pointers. + #[arg(long)] + generate_block: bool, + /// Generate string constants as `&CStr` instead of `&[u8]`. + #[arg(long)] + generate_cstr: bool, + /// Use extern crate instead of use for block. + #[arg(long)] + block_extern_crate: bool, + /// Do not trust the libclang-provided mangling + #[arg(long)] + distrust_clang_mangling: bool, + /// Output bindings for builtin definitions, e.g. __builtin_va_list. + #[arg(long)] + builtins: bool, + /// Use the given PREFIX before raw types instead of ::std::os::raw. + #[arg(long, value_name = "PREFIX")] + ctypes_prefix: Option, + /// Use the given PREFIX for anonymous fields. + #[arg(long, value_name = "PREFIX")] + anon_fields_prefix: Option, + /// Time the different bindgen phases and print to stderr + #[arg(long)] + time_phases: bool, + /// Output the Clang AST for debugging purposes. + #[arg(long)] + emit_clang_ast: bool, + /// Output our internal IR for debugging purposes. + #[arg(long)] + emit_ir: bool, + /// Dump a graphviz dot file to PATH. + #[arg(long, value_name = "PATH")] + emit_ir_graphviz: Option, + /// Enable support for C++ namespaces. + #[arg(long)] + enable_cxx_namespaces: bool, + /// Disable namespacing via mangling, causing bindgen to generate names like `Baz` instead of `foo_bar_Baz` for an input name `foo::bar::Baz`. + #[arg(long)] + disable_name_namespacing: bool, + /// Disable nested struct naming, causing bindgen to generate names like `bar` instead of `foo_bar` for a nested definition `struct foo { struct bar { } b; };`. + #[arg(long)] + disable_nested_struct_naming: bool, + /// Disable support for native Rust unions. + #[arg(long)] + disable_untagged_union: bool, + /// Suppress insertion of bindgen's version identifier into generated bindings. + #[arg(long)] + disable_header_comment: bool, + /// Do not generate bindings for functions or methods. This is useful when you only care about struct layouts. + #[arg(long)] + ignore_functions: bool, + /// Generate only given items, split by commas. Valid values are `functions`,`types`, `vars`, `methods`, `constructors` and `destructors`. + #[arg(long, value_parser = parse_codegen_config)] + generate: Option, + /// Do not generate bindings for methods. + #[arg(long)] + ignore_methods: bool, + /// Do not automatically convert floats to f32/f64. + #[arg(long)] + no_convert_floats: bool, + /// Do not prepend the enum name to constant or newtype variants. + #[arg(long)] + no_prepend_enum_name: bool, + /// Do not try to detect default include paths + #[arg(long)] + no_include_path_detection: bool, + /// Try to fit macro constants into types smaller than u32/i32 + #[arg(long)] + fit_macro_constant_types: bool, + /// Mark TYPE as opaque. + #[arg(long, value_name = "TYPE")] + opaque_type: Vec, + /// Write Rust bindings to OUTPUT. + #[arg(long, short, value_name = "OUTPUT")] + output: Option, + /// Add a raw line of Rust code at the beginning of output. + #[arg(long)] + raw_line: Vec, + /// Add a RAW_LINE of Rust code to a given module with name MODULE_NAME. + #[arg(long, number_of_values = 2, value_names = ["MODULE_NAME", "RAW_LINE"])] + module_raw_line: Vec, + #[arg(long, help = rust_target_help())] + rust_target: Option, + #[arg(long, value_name = "EDITION", help = rust_edition_help())] + rust_edition: Option, + /// Use types from Rust core instead of std. + #[arg(long)] + use_core: bool, + /// Conservatively generate inline namespaces to avoid name conflicts. + #[arg(long)] + conservative_inline_namespaces: bool, + /// Allowlist all the free-standing functions matching REGEX. Other non-allowlisted functions will not be generated. + #[arg(long, value_name = "REGEX")] + allowlist_function: Vec, + /// Generate inline functions. + #[arg(long)] + generate_inline_functions: bool, + /// Only generate types matching REGEX. Other non-allowlisted types will not be generated. + #[arg(long, value_name = "REGEX")] + allowlist_type: Vec, + /// Allowlist all the free-standing variables matching REGEX. Other non-allowlisted variables will not be generated. + #[arg(long, value_name = "REGEX")] + allowlist_var: Vec, + /// Allowlist all contents of PATH. + #[arg(long, value_name = "PATH")] + allowlist_file: Vec, + /// Allowlist all items matching REGEX. Other non-allowlisted items will not be generated. + #[arg(long, value_name = "REGEX")] + allowlist_item: Vec, + /// Print verbose error messages. + #[arg(long)] + verbose: bool, + /// Preprocess and dump the input header files to disk. Useful when debugging bindgen, using C-Reduce, or when filing issues. The resulting file will be named something like `__bindgen.i` or `__bindgen.ii`. + #[arg(long)] + dump_preprocessed_input: bool, + /// Do not record matching items in the regex sets. This disables reporting of unused items. + #[arg(long)] + no_record_matches: bool, + /// Do not bind size_t as usize (useful on platforms where those types are incompatible). + #[arg(long = "no-size_t-is-usize")] + no_size_t_is_usize: bool, + /// Do not format the generated bindings with rustfmt. This option is deprecated, please use + /// `--formatter=none` instead. + #[arg(long)] + no_rustfmt_bindings: bool, + /// Which FORMATTER should be used for the bindings + #[arg( + long, + value_name = "FORMATTER", + conflicts_with = "no_rustfmt_bindings" + )] + formatter: Option, + /// The absolute PATH to the rustfmt configuration file. The configuration file will be used for formatting the bindings. This parameter sets `formatter` to `rustfmt`. + #[arg(long, value_name = "PATH", conflicts_with = "no_rustfmt_bindings", value_parser=parse_rustfmt_config_path)] + rustfmt_configuration_file: Option, + /// Avoid deriving PartialEq for types matching REGEX. + #[arg(long, value_name = "REGEX")] + no_partialeq: Vec, + /// Avoid deriving Copy and Clone for types matching REGEX. + #[arg(long, value_name = "REGEX")] + no_copy: Vec, + /// Avoid deriving Debug for types matching REGEX. + #[arg(long, value_name = "REGEX")] + no_debug: Vec, + /// Avoid deriving/implementing Default for types matching REGEX. + #[arg(long, value_name = "REGEX")] + no_default: Vec, + /// Avoid deriving Hash for types matching REGEX. + #[arg(long, value_name = "REGEX")] + no_hash: Vec, + /// Add `#[must_use]` annotation to types matching REGEX. + #[arg(long, value_name = "REGEX")] + must_use_type: Vec, + /// Enables detecting unexposed attributes in functions (slow). Used to generate `#[must_use]` annotations. + #[arg(long)] + enable_function_attribute_detection: bool, + /// Use `*const [T; size]` instead of `*const T` for C arrays + #[arg(long)] + use_array_pointers_in_arguments: bool, + /// The NAME to be used in a #[link(wasm_import_module = ...)] statement + #[arg(long, value_name = "NAME")] + wasm_import_module_name: Option, + /// Attributes to apply to the extern function block. + #[arg(long, value_name = "ATTRS")] + extern_fn_block_attrs: Vec, + /// Use dynamic loading mode with the given library NAME. + #[arg(long, value_name = "NAME")] + dynamic_loading: Option, + /// Require successful linkage to all functions in the library. + #[arg(long)] + dynamic_link_require_all: bool, + /// Prefix the name of exported symbols. + #[arg(long)] + prefix_link_name: Option, + /// Makes generated bindings `pub` only for items if the items are publicly accessible in C++. + #[arg(long)] + respect_cxx_access_specs: bool, + /// Always translate enum integer types to native Rust integer types. + #[arg(long)] + translate_enum_integer_types: bool, + /// Generate types with C style naming. + #[arg(long)] + c_naming: bool, + /// Always output explicit padding fields. + #[arg(long)] + explicit_padding: bool, + /// Always be specific about the 'receiver' of a virtual function. + #[arg(long)] + use_specific_virtual_function_receiver: bool, + /// Use distinct char16_t + #[arg(long)] + use_distinct_char16_t: bool, + /// Output C++ overloaded operators + #[arg(long)] + represent_cxx_operators: bool, + /// Enables generation of vtable functions. + #[arg(long)] + vtable_generation: bool, + /// Enables sorting of code generation in a predefined manner. + #[arg(long)] + sort_semantically: bool, + /// Deduplicates extern blocks. + #[arg(long)] + merge_extern_blocks: bool, + /// Overrides the ABI of functions matching REGEX. The OVERRIDE value must be of the shape REGEX=ABI where ABI can be one of C, stdcall, efiapi, fastcall, thiscall, aapcs, win64 or C-unwind<.> + #[arg(long, value_name = "OVERRIDE", value_parser = parse_abi_override)] + override_abi: Vec<(Abi, String)>, + /// Wrap unsafe operations in unsafe blocks. + #[arg(long)] + wrap_unsafe_ops: bool, + /// Enable fallback for clang macro parsing. + #[arg(long)] + clang_macro_fallback: bool, + /// Set path for temporary files generated by fallback for clang macro parsing. + #[arg(long)] + clang_macro_fallback_build_dir: Option, + /// Use DSTs to represent structures with flexible array members. + #[arg(long)] + flexarray_dst: bool, + /// Derive custom traits on any kind of type. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a comma-separated list of derive macros. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)] + with_derive_custom: Vec<(Vec, String)>, + /// Derive custom traits on a `struct`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a comma-separated list of derive macros. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)] + with_derive_custom_struct: Vec<(Vec, String)>, + /// Derive custom traits on an `enum`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a comma-separated list of derive macros. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)] + with_derive_custom_enum: Vec<(Vec, String)>, + /// Derive custom traits on a `union`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a comma-separated list of derive macros. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)] + with_derive_custom_union: Vec<(Vec, String)>, + /// Add custom attributes on any kind of type. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a comma-separated list of attributes. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)] + with_attribute_custom: Vec<(Vec, String)>, + /// Add custom attributes on a `struct`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a comma-separated list of attributes. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)] + with_attribute_custom_struct: Vec<(Vec, String)>, + /// Add custom attributes on an `enum`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a comma-separated list of attributes. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)] + with_attribute_custom_enum: Vec<(Vec, String)>, + /// Add custom attributes on a `union`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a comma-separated list of attributes. + #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)] + with_attribute_custom_union: Vec<(Vec, String)>, + /// Generate wrappers for `static` and `static inline` functions. + #[arg(long)] + wrap_static_fns: bool, + /// Sets the PATH for the source file that must be created due to the presence of `static` and + /// `static inline` functions. + #[arg(long, value_name = "PATH")] + wrap_static_fns_path: Option, + /// Sets the SUFFIX added to the extern wrapper functions generated for `static` and `static + /// inline` functions. + #[arg(long, value_name = "SUFFIX")] + wrap_static_fns_suffix: Option, + /// Set the default VISIBILITY of fields, including bitfields and accessor methods for + /// bitfields. This flag is ignored if the `--respect-cxx-access-specs` flag is used. + #[arg(long, value_name = "VISIBILITY")] + default_visibility: Option, + /// Whether to generate C++ functions marked with "=delete" even though they + /// can't be called. + #[arg(long)] + generate_deleted_functions: bool, + /// Whether to generate C++ "pure virtual" functions even though they can't + /// be called. + #[arg(long)] + generate_pure_virtual_functions: bool, + /// Whether to generate C++ private functions even though they can't + /// be called. + #[arg(long)] + generate_private_functions: bool, + /// Whether to emit diagnostics or not. + #[cfg(feature = "experimental")] + #[arg(long, requires = "experimental")] + emit_diagnostics: bool, + /// Generates completions for the specified SHELL, sends them to `stdout` and exits. + #[arg(long, value_name = "SHELL")] + generate_shell_completions: Option, + /// Enables experimental features. + #[arg(long)] + experimental: bool, + /// Prints the version, and exits + #[arg(short = 'V', long)] + version: bool, + /// Arguments to be passed straight through to clang. + clang_args: Vec, +} + +/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. +pub fn builder_from_flags( + args: I, +) -> Result<(Builder, Box, bool), io::Error> +where + I: Iterator, +{ + let command = BindgenCommand::parse_from(args); + + let BindgenCommand { + header, + depfile, + default_enum_style, + bitfield_enum, + newtype_enum, + newtype_global_enum, + rustified_enum, + rustified_non_exhaustive_enum, + constified_enum, + constified_enum_module, + default_macro_constant_type, + default_alias_style, + normal_alias, + new_type_alias, + new_type_alias_deref, + default_non_copy_union_style, + bindgen_wrapper_union, + manually_drop_union, + blocklist_type, + blocklist_function, + blocklist_item, + blocklist_file, + blocklist_var, + no_layout_tests, + no_derive_copy, + no_derive_debug, + no_derive_default, + impl_debug, + impl_partialeq, + with_derive_default, + with_derive_hash, + with_derive_partialeq, + with_derive_partialord, + with_derive_eq, + with_derive_ord, + no_doc_comments, + no_recursive_allowlist, + objc_extern_crate, + nonnull_references, + generate_block, + generate_cstr, + block_extern_crate, + distrust_clang_mangling, + builtins, + ctypes_prefix, + anon_fields_prefix, + time_phases, + emit_clang_ast, + emit_ir, + emit_ir_graphviz, + enable_cxx_namespaces, + disable_name_namespacing, + disable_nested_struct_naming, + disable_untagged_union, + disable_header_comment, + ignore_functions, + generate, + ignore_methods, + no_convert_floats, + no_prepend_enum_name, + no_include_path_detection, + fit_macro_constant_types, + opaque_type, + output, + raw_line, + module_raw_line, + rust_target, + rust_edition, + use_core, + conservative_inline_namespaces, + allowlist_function, + generate_inline_functions, + allowlist_type, + allowlist_var, + allowlist_file, + allowlist_item, + verbose, + dump_preprocessed_input, + no_record_matches, + no_size_t_is_usize, + no_rustfmt_bindings, + formatter, + rustfmt_configuration_file, + no_partialeq, + no_copy, + no_debug, + no_default, + no_hash, + must_use_type, + enable_function_attribute_detection, + use_array_pointers_in_arguments, + wasm_import_module_name, + extern_fn_block_attrs, + dynamic_loading, + dynamic_link_require_all, + prefix_link_name, + respect_cxx_access_specs, + translate_enum_integer_types, + c_naming, + explicit_padding, + use_specific_virtual_function_receiver, + use_distinct_char16_t, + represent_cxx_operators, + vtable_generation, + sort_semantically, + merge_extern_blocks, + override_abi, + wrap_unsafe_ops, + clang_macro_fallback, + clang_macro_fallback_build_dir, + flexarray_dst, + with_derive_custom, + with_derive_custom_struct, + with_derive_custom_enum, + with_derive_custom_union, + with_attribute_custom, + with_attribute_custom_struct, + with_attribute_custom_enum, + with_attribute_custom_union, + wrap_static_fns, + wrap_static_fns_path, + wrap_static_fns_suffix, + default_visibility, + generate_deleted_functions, + generate_pure_virtual_functions, + generate_private_functions, + #[cfg(feature = "experimental")] + emit_diagnostics, + generate_shell_completions, + experimental: _, + version, + clang_args, + } = command; + + if let Some(shell) = generate_shell_completions { + clap_complete::generate( + shell, + &mut BindgenCommand::command(), + "bindgen", + &mut io::stdout(), + ); + + exit(0) + } + + if version { + println!( + "bindgen {}", + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown") + ); + if verbose { + println!("Clang: {}", crate::clang_version().full); + } + + exit(0) + } + + if header.is_none() { + return Err(io::Error::new(io::ErrorKind::Other, "Header not found")); + } + + let mut builder = builder(); + + #[derive(Debug)] + struct PrefixLinkNameCallback { + prefix: String, + } + + impl ParseCallbacks for PrefixLinkNameCallback { + fn generated_link_name_override( + &self, + item_info: ItemInfo<'_>, + ) -> Option { + let mut prefix = self.prefix.clone(); + prefix.push_str(item_info.name); + Some(prefix) + } + } + + #[derive(Debug)] + struct CustomDeriveCallback { + derives: Vec, + kind: Option, + regex_set: RegexSet, + } + + impl ParseCallbacks for CustomDeriveCallback { + fn cli_args(&self) -> Vec { + let mut args = vec![]; + + let flag = match &self.kind { + None => "--with-derive-custom", + Some(TypeKind::Struct) => "--with-derive-custom-struct", + Some(TypeKind::Enum) => "--with-derive-custom-enum", + Some(TypeKind::Union) => "--with-derive-custom-union", + }; + + let derives = self.derives.join(","); + + for item in self.regex_set.get_items() { + args.extend_from_slice(&[ + flag.to_owned(), + format!("{item}={derives}"), + ]); + } + + args + } + + fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec { + if self.kind.map_or(true, |kind| kind == info.kind) && + self.regex_set.matches(info.name) + { + return self.derives.clone(); + } + vec![] + } + } + + #[derive(Debug)] + struct CustomAttributeCallback { + attributes: Vec, + kind: Option, + regex_set: RegexSet, + } + + impl ParseCallbacks for CustomAttributeCallback { + fn cli_args(&self) -> Vec { + let mut args = vec![]; + + let flag = match &self.kind { + None => "--with-attribute-custom", + Some(TypeKind::Struct) => "--with-attribute-custom-struct", + Some(TypeKind::Enum) => "--with-attribute-custom-enum", + Some(TypeKind::Union) => "--with-attribute-custom-union", + }; + + let attributes = self.attributes.join(","); + + for item in self.regex_set.get_items() { + args.extend_from_slice(&[ + flag.to_owned(), + format!("{item}={attributes}"), + ]); + } + + args + } + + fn add_attributes(&self, info: &AttributeInfo<'_>) -> Vec { + if self.kind.map_or(true, |kind| kind == info.kind) && + self.regex_set.matches(info.name) + { + return self.attributes.clone(); + } + vec![] + } + } + + /// Macro used to apply CLI arguments to a builder. + /// + /// This is done by passing an identifier for each argument and a function to be applied over + /// the builder. For example: + /// ```rust,ignore + /// fn apply_arg(builder: Builder, arg_value: Value) -> Builder { + /// todo!() + /// } + /// + /// apply_args!( + /// builder { + /// arg => apply_arg, + /// } + /// ); + /// ``` + /// + /// If the identifier of the argument is the same as an already existing builder method then + /// you can omit the second part: + /// ```rust,ignore + /// apply_args!( + /// builder { + /// arg + /// } + /// ); + /// ``` + /// Which expands to the same code as: + /// ```rust,ignore + /// apply_args!( + /// builder { + /// arg => Builder::arg, + /// } + /// ); + /// ``` + macro_rules! apply_args { + ($builder:ident {}) => { $builder }; + ($builder:ident {$arg:ident => $function:expr, $($token:tt)*}) => { + { + $builder = CliArg::apply($arg, $builder, $function); + apply_args!($builder {$($token)*}) + } + }; + ($builder:ident {$arg:ident, $($token:tt)*}) => { + { + $builder = CliArg::apply($arg, $builder, Builder::$arg); + apply_args!($builder {$($token)*}) + } + } + } + + builder = apply_args!( + builder { + header, + rust_target, + rust_edition, + default_enum_style, + bitfield_enum, + newtype_enum, + newtype_global_enum, + rustified_enum, + rustified_non_exhaustive_enum, + constified_enum, + constified_enum_module, + default_macro_constant_type, + default_alias_style, + normal_alias => Builder::type_alias, + new_type_alias, + new_type_alias_deref, + default_non_copy_union_style, + bindgen_wrapper_union, + manually_drop_union, + blocklist_type, + blocklist_function, + blocklist_item, + blocklist_file, + blocklist_var, + builtins => |b, _| b.emit_builtins(), + no_layout_tests => |b, _| b.layout_tests(false), + no_derive_copy => |b, _| b.derive_copy(false), + no_derive_debug => |b, _| b.derive_debug(false), + impl_debug, + impl_partialeq, + with_derive_default => Builder::derive_default, + with_derive_hash => Builder::derive_hash, + with_derive_partialeq => Builder::derive_partialeq, + with_derive_partialord => Builder::derive_partialord, + with_derive_eq => Builder::derive_eq, + with_derive_ord => Builder::derive_ord, + no_derive_default => |b, _| b.derive_default(false), + no_prepend_enum_name => |b, _| b.prepend_enum_name(false), + no_include_path_detection => |b, _| b.detect_include_paths(false), + fit_macro_constant_types => Builder::fit_macro_constants, + time_phases, + use_array_pointers_in_arguments => Builder::array_pointers_in_arguments, + wasm_import_module_name, + extern_fn_block_attrs => Builder::extern_fn_block_attrs, + ctypes_prefix, + anon_fields_prefix, + generate => Builder::with_codegen_config, + emit_clang_ast => |b, _| b.emit_clang_ast(), + emit_ir => |b, _| b.emit_ir(), + emit_ir_graphviz, + enable_cxx_namespaces => |b, _| b.enable_cxx_namespaces(), + enable_function_attribute_detection => |b, _| b.enable_function_attribute_detection(), + disable_name_namespacing => |b, _| b.disable_name_namespacing(), + disable_nested_struct_naming => |b, _| b.disable_nested_struct_naming(), + disable_untagged_union => |b, _| b.disable_untagged_union(), + disable_header_comment => |b, _| b.disable_header_comment(), + ignore_functions => |b, _| b.ignore_functions(), + ignore_methods => |b, _| b.ignore_methods(), + no_convert_floats => |b, _| b.no_convert_floats(), + no_doc_comments => |b, _| b.generate_comments(false), + no_recursive_allowlist => |b, _| b.allowlist_recursively(false), + objc_extern_crate, + nonnull_references => |b, _| b.generate_cxx_nonnull_references(true), + generate_block, + generate_cstr, + block_extern_crate, + opaque_type, + raw_line, + use_core => |b, _| b.use_core(), + distrust_clang_mangling => |b, _| b.trust_clang_mangling(false), + conservative_inline_namespaces => |b, _| b.conservative_inline_namespaces(), + generate_inline_functions, + allowlist_function, + allowlist_type, + allowlist_var, + allowlist_file, + allowlist_item, + clang_args => Builder::clang_arg, + no_record_matches => |b, _| b.record_matches(false), + no_size_t_is_usize => |b, _| b.size_t_is_usize(false), + no_rustfmt_bindings => |b, _| b.formatter(Formatter::None), + formatter, + no_partialeq, + no_copy, + no_debug, + no_default, + no_hash, + must_use_type, + dynamic_loading => Builder::dynamic_library_name, + dynamic_link_require_all, + prefix_link_name => |b, prefix| b.parse_callbacks(Box::new(PrefixLinkNameCallback { prefix })), + respect_cxx_access_specs, + translate_enum_integer_types, + c_naming, + explicit_padding, + use_specific_virtual_function_receiver, + use_distinct_char16_t, + represent_cxx_operators, + vtable_generation, + sort_semantically, + merge_extern_blocks, + override_abi => |b, (abi, regex)| b.override_abi(abi, regex), + wrap_unsafe_ops, + clang_macro_fallback => |b, _| b.clang_macro_fallback(), + clang_macro_fallback_build_dir, + flexarray_dst, + wrap_static_fns, + wrap_static_fns_path, + wrap_static_fns_suffix, + default_visibility, + generate_deleted_functions, + generate_pure_virtual_functions, + generate_private_functions, + } + ); + + let mut values = module_raw_line.into_iter(); + while let Some(module) = values.next() { + let line = values.next().unwrap(); + builder = builder.module_raw_line(module, line); + } + + let output = if let Some(path) = &output { + let file = File::create(path)?; + if let Some(depfile) = depfile { + builder = builder.depfile(path, depfile); + } + Box::new(io::BufWriter::new(file)) as Box + } else { + if let Some(depfile) = depfile { + builder = builder.depfile("-", depfile); + } + Box::new(io::BufWriter::new(io::stdout())) as Box + }; + + if dump_preprocessed_input { + builder.dump_preprocessed_input()?; + } + + if let Some(path) = rustfmt_configuration_file { + builder = builder.rustfmt_configuration_file(Some(path)); + } + + for (custom_derives, kind, _name) in [ + (with_derive_custom, None, "--with-derive-custom"), + ( + with_derive_custom_struct, + Some(TypeKind::Struct), + "--with-derive-custom-struct", + ), + ( + with_derive_custom_enum, + Some(TypeKind::Enum), + "--with-derive-custom-enum", + ), + ( + with_derive_custom_union, + Some(TypeKind::Union), + "--with-derive-custom-union", + ), + ] { + #[cfg(feature = "experimental")] + let name = emit_diagnostics.then_some(_name); + + for (derives, regex) in custom_derives { + let mut regex_set = RegexSet::default(); + regex_set.insert(regex); + + #[cfg(feature = "experimental")] + regex_set.build_with_diagnostics(false, name); + #[cfg(not(feature = "experimental"))] + regex_set.build(false); + + builder = builder.parse_callbacks(Box::new(CustomDeriveCallback { + derives, + kind, + regex_set, + })); + } + } + + for (custom_attributes, kind, _name) in [ + (with_attribute_custom, None, "--with-attribute-custom"), + ( + with_attribute_custom_struct, + Some(TypeKind::Struct), + "--with-attribute-custom-struct", + ), + ( + with_attribute_custom_enum, + Some(TypeKind::Enum), + "--with-attribute-custom-enum", + ), + ( + with_attribute_custom_union, + Some(TypeKind::Union), + "--with-attribute-custom-union", + ), + ] { + #[cfg(feature = "experimental")] + let name = emit_diagnostics.then_some(_name); + + for (attributes, regex) in custom_attributes { + let mut regex_set = RegexSet::default(); + regex_set.insert(regex); + + #[cfg(feature = "experimental")] + regex_set.build_with_diagnostics(false, name); + #[cfg(not(feature = "experimental"))] + regex_set.build(false); + + builder = + builder.parse_callbacks(Box::new(CustomAttributeCallback { + attributes, + kind, + regex_set, + })); + } + } + + #[cfg(feature = "experimental")] + if emit_diagnostics { + builder = builder.emit_diagnostics(); + } + + Ok((builder, output, verbose)) +} + +/// Trait for CLI arguments that can be applied to a [`Builder`]. +trait CliArg { + /// The value of this argument. + type Value; + + /// Apply the current argument to the passed [`Builder`]. + fn apply( + self, + builder: Builder, + f: impl Fn(Builder, Self::Value) -> Builder, + ) -> Builder; +} + +/// Boolean arguments are applied when they evaluate to `true`. +impl CliArg for bool { + type Value = bool; + + fn apply( + self, + mut builder: Builder, + f: impl Fn(Builder, Self::Value) -> Builder, + ) -> Builder { + if self { + builder = f(builder, self); + } + + builder + } +} + +/// Optional arguments are applied when they are `Some`. +impl CliArg for Option { + type Value = T; + + fn apply( + self, + mut builder: Builder, + f: impl Fn(Builder, Self::Value) -> Builder, + ) -> Builder { + if let Some(value) = self { + builder = f(builder, value); + } + + builder + } +} + +/// Multiple valued arguments are applied once for each value. +impl CliArg for Vec { + type Value = T; + + fn apply( + self, + mut builder: Builder, + f: impl Fn(Builder, Self::Value) -> Builder, + ) -> Builder { + for value in self { + builder = f(builder, value); + } + + builder + } +} diff --git a/bindgen/options/helpers.rs b/bindgen/options/helpers.rs new file mode 100644 index 0000000000..1816c72b57 --- /dev/null +++ b/bindgen/options/helpers.rs @@ -0,0 +1,43 @@ +/// Helper function that appends extra documentation to [`crate::Builder`] methods that support regular +/// expressions in their input. +macro_rules! regex_option { + ($(#[$attrs:meta])* pub fn $($tokens:tt)*) => { + $(#[$attrs])* + /// + /// Regular expressions are supported. Check the [regular expression + /// arguments](./struct.Builder.html#regular-expression-arguments) section and the + /// [regex](https://docs.rs/regex) crate documentation for further information. + pub fn $($tokens)* + }; +} + +/// Helper macro to set the default value of each option. +/// +/// This macro is an internal implementation detail of the `options` macro and should not be used +/// directly. +macro_rules! default { + () => { + Default::default() + }; + ($expr:expr) => { + $expr + }; +} + +/// Helper macro to set the conversion to CLI arguments for each option. +/// +/// This macro is an internal implementation detail of the `options` macro and should not be used +/// directly. +macro_rules! as_args { + ($flag:literal) => { + |field, args| AsArgs::as_args(field, args, $flag) + }; + ($expr:expr) => { + $expr + }; +} + +/// Helper function to ignore an option when converting it into CLI arguments. +/// +/// This function is only used inside `options` and should not be used in other contexts. +pub(super) fn ignore(_: &T, _: &mut Vec) {} diff --git a/bindgen/options/mod.rs b/bindgen/options/mod.rs new file mode 100644 index 0000000000..b9b33a850b --- /dev/null +++ b/bindgen/options/mod.rs @@ -0,0 +1,2332 @@ +//! Declarations and setter methods for `bindgen` options. +//! +//! The main entry point of this module is the `options` macro. +#[macro_use] +mod helpers; +mod as_args; +#[cfg(feature = "__cli")] +pub(crate) mod cli; + +use crate::callbacks::ParseCallbacks; +use crate::codegen::{ + AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle, +}; +use crate::deps::DepfileSpec; +use crate::features::{RustEdition, RustFeatures, RustTarget}; +use crate::regex_set::RegexSet; +use crate::Abi; +use crate::Builder; +use crate::CodegenConfig; +use crate::FieldVisibilityKind; +use crate::Formatter; +use crate::HashMap; +use crate::DEFAULT_ANON_FIELDS_PREFIX; + +use std::env; +use std::path::{Path, PathBuf}; +use std::rc::Rc; + +use as_args::AsArgs; +use helpers::ignore; + +/// Macro used to generate the [`BindgenOptions`] type and the [`Builder`] setter methods for each +/// one of the fields of `BindgenOptions`. +/// +/// The input format of this macro resembles a `struct` pattern. Each field of the `BindgenOptions` +/// type is declared by adding the name of the field and its type using the `name: type` syntax and +/// a block of code with the following items: +/// +/// - `default`: The default value for the field. If this item is omitted, `Default::default()` is +/// used instead, meaning that the type of the field must implement `Default`. +/// - `methods`: A block of code containing methods for the `Builder` type. These methods should be +/// related to the field being declared. +/// - `as_args`: This item declares how the field should be converted into a valid CLI argument for +/// `bindgen` and is used in the [`Builder::command_line_flags`] method which is used to do a +/// roundtrip test of the CLI args in the `bindgen-test` crate. This item can take one of the +/// following: +/// - A string literal with the flag if the type of the field implements the [`AsArgs`] trait. +/// - A closure with the signature `|field, args: &mut Vec| -> ()` that pushes arguments +/// into the `args` buffer based on the value of the field. This is used if the field does not +/// implement `AsArgs` or if the implementation of the trait is not logically correct for the +/// option and a custom behavior must be taken into account. +/// - The `ignore` literal, which does not emit any CLI arguments for this field. This is useful +/// if the field cannot be used from the `bindgen` CLI. +/// +/// As an example, this would be the declaration of a `bool` field called `be_fun` whose default +/// value is `false` (the `Default` value for `bool`): +/// ```rust,ignore +/// be_fun: bool { +/// methods: { +/// /// Ask `bindgen` to be fun. This option is disabled by default. +/// fn be_fun(mut self) -> Self { +/// self.options.be_fun = true; +/// self +/// } +/// }, +/// as_args: "--be-fun", +/// } +/// ``` +/// +/// However, we could also set the `be_fun` field to `true` by default and use a `--not-fun` flag +/// instead. This means that we have to add the `default` item and use a closure in the `as_args` +/// item: +/// ```rust,ignore +/// be_fun: bool { +/// default: true, +/// methods: { +/// /// Ask `bindgen` to not be fun. `bindgen` is fun by default. +/// fn not_fun(mut self) -> Self { +/// self.options.be_fun = false; +/// self +/// } +/// }, +/// as_args: |be_fun, args| (!be_fun).as_args(args, "--not-fun"), +/// } +/// ``` +/// More complex examples can be found in the sole invocation of this macro. +macro_rules! options { + ($( + $(#[doc = $docs:literal])+ + $field:ident: $ty:ty { + $(default: $default:expr,)? + methods: {$($methods_tokens:tt)*}$(,)? + as_args: $as_args:expr$(,)? + }$(,)? + )*) => { + #[derive(Debug, Clone)] + pub(crate) struct BindgenOptions { + $($(#[doc = $docs])* pub(crate) $field: $ty,)* + } + + impl Default for BindgenOptions { + fn default() -> Self { + Self { + $($field: default!($($default)*),)* + } + } + } + + impl Builder { + /// Generates the command line flags used to create this [`Builder`]. + pub fn command_line_flags(&self) -> Vec { + let mut args = vec![]; + + let headers = match self.options.input_headers.split_last() { + Some((header, headers)) => { + // The last input header is passed as an argument in the first position. + args.push(header.clone().into()); + headers + }, + None => &[] + }; + + $({ + let func: fn(&$ty, &mut Vec) = as_args!($as_args); + func(&self.options.$field, &mut args); + })* + + // Add the `--experimental` flag if `bindgen` is built with the `experimental` + // feature. + if cfg!(feature = "experimental") { + args.push("--experimental".to_owned()); + } + + // Add all the clang arguments. + args.push("--".to_owned()); + + if !self.options.clang_args.is_empty() { + args.extend(self.options.clang_args.iter().map(|s| s.clone().into())); + } + + // We need to pass all but the last header via the `-include` clang argument. + for header in headers { + args.push("-include".to_owned()); + args.push(header.clone().into()); + } + + args + } + + $($($methods_tokens)*)* + } + }; +} + +options! { + /// Whether to specify the type of a virtual function receiver + use_specific_virtual_function_receiver: bool { + methods: { + /// Normally, virtual functions have void* as their 'this' type. + /// If this flag is enabled, override that behavior to indicate a + /// pointer of the specific type. + /// Disabled by default. + pub fn use_specific_virtual_function_receiver(mut self, doit: bool) -> Builder { + self.options.use_specific_virtual_function_receiver = doit; + self + } + }, + as_args: "--use-specific-virtual-function-receiver", + }, + + /// Whether we should distinguish between C++'s `char16_t` and `u16`. + /// The C++ type `char16_t` is its own special type; it's not a typedef + /// of some other integer (this differs from C). + /// As standard, bindgen represents C++ `char16_t` as `u16`. + /// Rust does not have a `std::os::raw::c_char16_t` type, and thus + /// we can't use a built-in Rust type in the generated bindings (and + /// nor would it be appropriate as it's a C++-specific type.) + /// But for some uses of bindgen, especially when downstream + /// post-processing occurs, it's important to distinguish `char16_t` + /// from normal `uint16_t`. When this option is enabled, bindgen + /// generates a fake type called `bindgen_cchar16_t`. Downstream + /// code post-processors should arrange to replace this with a + /// real type. + use_distinct_char16_t: bool { + methods: { + /// If this is true, denote `char16_t` as a separate type from `u16`. + /// Disabled by default. + pub fn use_distinct_char16_t(mut self, doit: bool) -> Builder { + self.options.use_distinct_char16_t = doit; + self + } + }, + as_args: "--use-distinct-char16-t", + }, + /// Whether we should output C++ overloaded operators. By itself, + /// this option is not sufficient to produce valid output, because + /// such operators will have names that are not acceptable Rust + /// names (for example `operator=`). If you use this option, you'll also + /// have to rename the resulting functions - for example by using + /// [`ParseCallbacks::generated_name_override`]. + represent_cxx_operators: bool { + methods: { + /// If this is true, output existence of C++ overloaded operators. + /// At present, only operator= is noted. + /// Disabled by default. + pub fn represent_cxx_operators(mut self, doit: bool) -> Builder { + self.options.represent_cxx_operators = doit; + self + } + }, + as_args: "--represent-cxx-operators", + }, + + /// Types that have been blocklisted and should not appear anywhere in the generated code. + blocklisted_types: RegexSet { + methods: { + regex_option! { + /// Do not generate any bindings for the given type. + /// + /// This option is not recursive, meaning that it will only block types whose names + /// explicitly match the argument of this method. + pub fn blocklist_type>(mut self, arg: T) -> Builder { + self.options.blocklisted_types.insert(arg); + self + } + } + }, + as_args: "--blocklist-type", + }, + /// Functions that have been blocklisted and should not appear in the generated code. + blocklisted_functions: RegexSet { + methods: { + regex_option! { + /// Do not generate any bindings for the given function. + /// + /// This option is not recursive, meaning that it will only block functions whose + /// names explicitly match the argument of this method. + pub fn blocklist_function>(mut self, arg: T) -> Builder { + self.options.blocklisted_functions.insert(arg); + self + } + } + }, + as_args: "--blocklist-function", + }, + /// Items that have been blocklisted and should not appear in the generated code. + blocklisted_items: RegexSet { + methods: { + regex_option! { + /// Do not generate any bindings for the given item, regardless of whether it is a + /// type, function, module, etc. + /// + /// This option is not recursive, meaning that it will only block items whose names + /// explicitly match the argument of this method. + pub fn blocklist_item>(mut self, arg: T) -> Builder { + self.options.blocklisted_items.insert(arg); + self + } + } + }, + as_args: "--blocklist-item", + }, + /// Files whose contents should be blocklisted and should not appear in the generated code. + blocklisted_files: RegexSet { + methods: { + regex_option! { + /// Do not generate any bindings for the contents of the given file, regardless of + /// whether the contents of the file are types, functions, modules, etc. + /// + /// This option is not recursive, meaning that it will only block files whose names + /// explicitly match the argument of this method. + /// + /// This method will use the argument to match the complete path of the file + /// instead of a section of it. + pub fn blocklist_file>(mut self, arg: T) -> Builder { + self.options.blocklisted_files.insert(arg); + self + } + } + }, + as_args: "--blocklist-file", + }, + /// Variables that have been blocklisted and should not appear in the generated code. + blocklisted_vars: RegexSet { + methods: { + regex_option! { + /// Do not generate any bindings for the given variable. + /// + /// This option is not recursive, meaning that it will only block variables whose + /// names explicitly match the argument of this method. + pub fn blocklist_var>(mut self, arg: T) -> Builder { + self.options.blocklisted_vars.insert(arg); + self + } + } + }, + as_args: "--blocklist-var", + }, + /// Types that should be treated as opaque structures in the generated code. + opaque_types: RegexSet { + methods: { + regex_option! { + /// Treat the given type as opaque in the generated bindings. + /// + /// Opaque in this context means that none of the generated bindings will contain + /// information about the inner representation of the type and the type itself will + /// be represented as a chunk of bytes with the alignment and size of the type. + pub fn opaque_type>(mut self, arg: T) -> Builder { + self.options.opaque_types.insert(arg); + self + } + } + }, + as_args: "--opaque-type", + }, + /// The explicit `rustfmt` path. + rustfmt_path: Option { + methods: { + /// Set an explicit path to the `rustfmt` binary. + /// + /// This option only comes into effect if `rustfmt` is set to be the formatter used by + /// `bindgen`. Check the documentation of the [`Builder::formatter`] method for more + /// information. + pub fn with_rustfmt>(mut self, path: P) -> Self { + self.options.rustfmt_path = Some(path.into()); + self + } + }, + // This option cannot be set from the CLI. + as_args: ignore, + }, + /// The path to which we should write a Makefile-syntax depfile (if any). + depfile: Option { + methods: { + /// Add a depfile output which will be written alongside the generated bindings. + pub fn depfile, D: Into>( + mut self, + output_module: H, + depfile: D, + ) -> Builder { + self.options.depfile = Some(DepfileSpec { + output_module: output_module.into(), + depfile_path: depfile.into(), + }); + self + } + }, + as_args: |depfile, args| { + if let Some(depfile) = depfile { + args.push("--depfile".into()); + args.push(depfile.depfile_path.display().to_string()); + } + }, + }, + /// Types that have been allowlisted and should appear in the generated code. + allowlisted_types: RegexSet { + methods: { + regex_option! { + /// Generate bindings for the given type. + /// + /// This option is transitive by default. Check the documentation of the + /// [`Builder::allowlist_recursively`] method for further information. + pub fn allowlist_type>(mut self, arg: T) -> Builder { + self.options.allowlisted_types.insert(arg); + self + } + } + }, + as_args: "--allowlist-type", + }, + /// Functions that have been allowlisted and should appear in the generated code. + allowlisted_functions: RegexSet { + methods: { + regex_option! { + /// Generate bindings for the given function. + /// + /// This option is transitive by default. Check the documentation of the + /// [`Builder::allowlist_recursively`] method for further information. + pub fn allowlist_function>(mut self, arg: T) -> Builder { + self.options.allowlisted_functions.insert(arg); + self + } + } + }, + as_args: "--allowlist-function", + }, + /// Variables that have been allowlisted and should appear in the generated code. + allowlisted_vars: RegexSet { + methods: { + regex_option! { + /// Generate bindings for the given variable. + /// + /// This option is transitive by default. Check the documentation of the + /// [`Builder::allowlist_recursively`] method for further information. + pub fn allowlist_var>(mut self, arg: T) -> Builder { + self.options.allowlisted_vars.insert(arg); + self + } + } + }, + as_args: "--allowlist-var", + }, + /// Files whose contents have been allowlisted and should appear in the generated code. + allowlisted_files: RegexSet { + methods: { + regex_option! { + /// Generate bindings for the content of the given file. + /// + /// This option is transitive by default. Check the documentation of the + /// [`Builder::allowlist_recursively`] method for further information. + /// + /// This method will use the argument to match the complete path of the file + /// instead of a section of it. + pub fn allowlist_file>(mut self, arg: T) -> Builder { + self.options.allowlisted_files.insert(arg); + self + } + } + }, + as_args: "--allowlist-file", + }, + /// Items that have been allowlisted and should appear in the generated code. + allowlisted_items: RegexSet { + methods: { + regex_option! { + /// Generate bindings for the given item, regardless of whether it is a type, + /// function, module, etc. + /// + /// This option is transitive by default. Check the documentation of the + /// [`Builder::allowlist_recursively`] method for further information. + pub fn allowlist_item>(mut self, arg: T) -> Builder { + self.options.allowlisted_items.insert(arg); + self + } + } + }, + as_args: "--allowlist-item", + }, + /// The default style of for generated `enum`s. + default_enum_style: EnumVariation { + methods: { + /// Set the default style for generated `enum`s. + /// + /// If this method is not called, the [`EnumVariation::Consts`] style will be used by + /// default. + /// + /// To set the style for individual `enum`s, use [`Builder::bitfield_enum`], + /// [`Builder::newtype_enum`], [`Builder::newtype_global_enum`], + /// [`Builder::rustified_enum`], [`Builder::rustified_non_exhaustive_enum`], + /// [`Builder::constified_enum_module`] or [`Builder::constified_enum`]. + pub fn default_enum_style( + mut self, + arg: EnumVariation, + ) -> Builder { + self.options.default_enum_style = arg; + self + } + }, + as_args: |variation, args| { + if *variation != Default::default() { + args.push("--default-enum-style".to_owned()); + args.push(variation.to_string()); + } + }, + }, + /// `enum`s marked as bitfield-like. This is, newtypes with bitwise operations. + bitfield_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as being bitfield-like. + /// + /// This is similar to the [`Builder::newtype_enum`] style, but with the bitwise + /// operators implemented. + pub fn bitfield_enum>(mut self, arg: T) -> Builder { + self.options.bitfield_enums.insert(arg); + self + } + } + }, + as_args: "--bitfield-enum", + }, + /// `enum`s marked as newtypes. + newtype_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a newtype. + /// + /// This means that an integer newtype will be declared to represent the `enum` + /// type and its variants will be represented as constants inside of this type's + /// `impl` block. + pub fn newtype_enum>(mut self, arg: T) -> Builder { + self.options.newtype_enums.insert(arg); + self + } + } + }, + as_args: "--newtype-enum", + }, + /// `enum`s marked as global newtypes . + newtype_global_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a global newtype. + /// + /// This is similar to the [`Builder::newtype_enum`] style, but the constants for + /// each variant are free constants instead of being declared inside an `impl` + /// block for the newtype. + pub fn newtype_global_enum>(mut self, arg: T) -> Builder { + self.options.newtype_global_enums.insert(arg); + self + } + } + }, + as_args: "--newtype-global-enum", + }, + /// `enum`s marked as Rust `enum`s. + rustified_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a Rust `enum`. + /// + /// This means that each variant of the `enum` will be represented as a Rust `enum` + /// variant. + /// + /// **Use this with caution**, creating an instance of a Rust `enum` with an + /// invalid value will cause undefined behaviour. To avoid this, use the + /// [`Builder::newtype_enum`] style instead. + pub fn rustified_enum>(mut self, arg: T) -> Builder { + self.options.rustified_enums.insert(arg); + self + } + } + }, + as_args: "--rustified-enum", + }, + /// `enum`s marked as non-exhaustive Rust `enum`s. + rustified_non_exhaustive_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a non-exhaustive Rust `enum`. + /// + /// This is similar to the [`Builder::rustified_enum`] style, but the `enum` is + /// tagged with the `#[non_exhaustive]` attribute. + /// + /// **Use this with caution**, creating an instance of a Rust `enum` with an + /// invalid value will cause undefined behaviour, even if it's tagged with + /// `#[non_exhaustive]`. To avoid this, use the [`Builder::newtype_enum`] style + /// instead. + pub fn rustified_non_exhaustive_enum>(mut self, arg: T) -> Builder { + self.options.rustified_non_exhaustive_enums.insert(arg); + self + } + } + }, + as_args: "--rustified-non-exhaustive-enum", + }, + /// `enum`s marked as modules of constants. + constified_enum_modules: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a module with a set of integer constants. + pub fn constified_enum_module>(mut self, arg: T) -> Builder { + self.options.constified_enum_modules.insert(arg); + self + } + } + }, + as_args: "--constified-enum-module", + }, + /// `enum`s marked as a set of constants. + constified_enums: RegexSet { + methods: { + regex_option! { + /// Mark the given `enum` as a set of integer constants. + /// + /// This is similar to the [`Builder::constified_enum_module`] style, but the + /// constants are generated in the current module instead of in a new module. + pub fn constified_enum>(mut self, arg: T) -> Builder { + self.options.constified_enums.insert(arg); + self + } + } + }, + as_args: "--constified-enum", + }, + /// The default type signedness for C macro constants. + default_macro_constant_type: MacroTypeVariation { + methods: { + /// Set the default type signedness to be used for macro constants. + /// + /// If this method is not called, [`MacroTypeVariation::Unsigned`] is used by default. + /// + /// To set the type for individual macro constants, use the + /// [`ParseCallbacks::int_macro`] method. + pub fn default_macro_constant_type(mut self, arg: MacroTypeVariation) -> Builder { + self.options.default_macro_constant_type = arg; + self + } + + }, + as_args: |variation, args| { + if *variation != Default::default() { + args.push("--default-macro-constant-type".to_owned()); + args.push(variation.to_string()); + } + }, + }, + /// The default style of code generation for `typedef`s. + default_alias_style: AliasVariation { + methods: { + /// Set the default style of code generation for `typedef`s. + /// + /// If this method is not called, the [`AliasVariation::TypeAlias`] style is used by + /// default. + /// + /// To set the style for individual `typedefs`s, use [`Builder::type_alias`], + /// [`Builder::new_type_alias`] or [`Builder::new_type_alias_deref`]. + pub fn default_alias_style( + mut self, + arg: AliasVariation, + ) -> Builder { + self.options.default_alias_style = arg; + self + } + }, + as_args: |variation, args| { + if *variation != Default::default() { + args.push("--default-alias-style".to_owned()); + args.push(variation.to_string()); + } + }, + }, + /// `typedef` patterns that will use regular type aliasing. + type_alias: RegexSet { + methods: { + regex_option! { + /// Mark the given `typedef` as a regular Rust `type` alias. + /// + /// This is the default behavior, meaning that this method only comes into effect + /// if a style different from [`AliasVariation::TypeAlias`] was passed to the + /// [`Builder::default_alias_style`] method. + pub fn type_alias>(mut self, arg: T) -> Builder { + self.options.type_alias.insert(arg); + self + } + } + }, + as_args: "--type-alias", + }, + /// `typedef` patterns that will be aliased by creating a newtype. + new_type_alias: RegexSet { + methods: { + regex_option! { + /// Mark the given `typedef` as a Rust newtype by having the aliased + /// type be wrapped in a `struct` with `#[repr(transparent)]`. + /// + /// This method can be used to enforce stricter type checking. + pub fn new_type_alias>(mut self, arg: T) -> Builder { + self.options.new_type_alias.insert(arg); + self + } + } + }, + as_args: "--new-type-alias", + }, + /// `typedef` patterns that will be wrapped in a newtype implementing `Deref` and `DerefMut`. + new_type_alias_deref: RegexSet { + methods: { + regex_option! { + /// Mark the given `typedef` to be generated as a newtype that can be dereferenced. + /// + /// This is similar to the [`Builder::new_type_alias`] style, but the newtype + /// implements `Deref` and `DerefMut` with the aliased type as a target. + pub fn new_type_alias_deref>(mut self, arg: T) -> Builder { + self.options.new_type_alias_deref.insert(arg); + self + } + } + }, + as_args: "--new-type-alias-deref", + }, + /// The default style of code to generate for `union`s containing non-`Copy` members. + default_non_copy_union_style: NonCopyUnionStyle { + methods: { + /// Set the default style of code to generate for `union`s with non-`Copy` members. + /// + /// If this method is not called, the [`NonCopyUnionStyle::BindgenWrapper`] style is + /// used by default. + /// + /// To set the style for individual `union`s, use [`Builder::bindgen_wrapper_union`] or + /// [`Builder::manually_drop_union`]. + pub fn default_non_copy_union_style(mut self, arg: NonCopyUnionStyle) -> Self { + self.options.default_non_copy_union_style = arg; + self + } + }, + as_args: |style, args| { + if *style != Default::default() { + args.push("--default-non-copy-union-style".to_owned()); + args.push(style.to_string()); + } + }, + }, + /// The patterns marking non-`Copy` `union`s as using the `bindgen` generated wrapper. + bindgen_wrapper_union: RegexSet { + methods: { + regex_option! { + /// Mark the given `union` to use a `bindgen`-generated wrapper for its members if at + /// least one them is not `Copy`. + /// + /// This is the default behavior, meaning that this method only comes into effect + /// if a style different from [`NonCopyUnionStyle::BindgenWrapper`] was passed to + /// the [`Builder::default_non_copy_union_style`] method. + pub fn bindgen_wrapper_union>(mut self, arg: T) -> Self { + self.options.bindgen_wrapper_union.insert(arg); + self + } + } + }, + as_args: "--bindgen-wrapper-union", + }, + /// The patterns marking non-`Copy` `union`s as using the `ManuallyDrop` wrapper. + manually_drop_union: RegexSet { + methods: { + regex_option! { + /// Mark the given `union` to use [`::core::mem::ManuallyDrop`] for its members if + /// at least one of them is not `Copy`. + /// + /// The `ManuallyDrop` type was stabilized in Rust 1.20.0, do not use this option + /// if your target version is lower than this. + pub fn manually_drop_union>(mut self, arg: T) -> Self { + self.options.manually_drop_union.insert(arg); + self + } + } + + }, + as_args: "--manually-drop-union", + }, + + + /// Whether we should generate built-in definitions. + builtins: bool { + methods: { + /// Generate Rust bindings for built-in definitions (for example `__builtin_va_list`). + /// + /// Bindings for built-in definitions are not emitted by default. + pub fn emit_builtins(mut self) -> Builder { + self.options.builtins = true; + self + } + }, + as_args: "--builtins", + }, + /// Whether we should dump the Clang AST for debugging purposes. + emit_ast: bool { + methods: { + /// Emit the Clang AST to `stdout` for debugging purposes. + /// + /// The Clang AST is not emitted by default. + pub fn emit_clang_ast(mut self) -> Builder { + self.options.emit_ast = true; + self + } + }, + as_args: "--emit-clang-ast", + }, + /// Whether we should dump our IR for debugging purposes. + emit_ir: bool { + methods: { + /// Emit the `bindgen` internal representation to `stdout` for debugging purposes. + /// + /// This internal representation is not emitted by default. + pub fn emit_ir(mut self) -> Builder { + self.options.emit_ir = true; + self + } + }, + as_args: "--emit-ir", + }, + /// Output path for the `graphviz` DOT file. + emit_ir_graphviz: Option { + methods: { + /// Set the path for the file where the`bindgen` internal representation will be + /// emitted as a graph using the `graphviz` DOT language. + /// + /// This graph representation is not emitted by default. + pub fn emit_ir_graphviz>(mut self, path: T) -> Builder { + let path = path.into(); + self.options.emit_ir_graphviz = Some(path); + self + } + }, + as_args: "--emit-ir-graphviz", + }, + + /// Whether we should emulate C++ namespaces with Rust modules. + enable_cxx_namespaces: bool { + methods: { + /// Emulate C++ namespaces using Rust modules in the generated bindings. + /// + /// C++ namespaces are not emulated by default. + pub fn enable_cxx_namespaces(mut self) -> Builder { + self.options.enable_cxx_namespaces = true; + self + } + }, + as_args: "--enable-cxx-namespaces", + }, + /// Whether we should try to find unexposed attributes in functions. + enable_function_attribute_detection: bool { + methods: { + /// Enable detecting function attributes on C functions. + /// + /// This enables the following features: + /// - Add `#[must_use]` attributes to Rust items whose C counterparts are marked as so. + /// This feature also requires that the Rust target version supports the attribute. + /// - Set `!` as the return type for Rust functions whose C counterparts are marked as + /// diverging. + /// + /// This option can be quite slow in some cases (check [#1465]), so it is disabled by + /// default. + /// + /// [#1465]: https://github.com/rust-lang/rust-bindgen/issues/1465 + pub fn enable_function_attribute_detection(mut self) -> Self { + self.options.enable_function_attribute_detection = true; + self + } + + }, + as_args: "--enable-function-attribute-detection", + }, + /// Whether we should avoid mangling names with namespaces. + disable_name_namespacing: bool { + methods: { + /// Disable name auto-namespacing. + /// + /// By default, `bindgen` mangles names like `foo::bar::Baz` to look like `foo_bar_Baz` + /// instead of just `Baz`. This method disables that behavior. + /// + /// Note that this does not change the names used for allowlisting and blocklisting, + /// which should still be mangled with the namespaces. Additionally, this option may + /// cause `bindgen` to generate duplicate names. + pub fn disable_name_namespacing(mut self) -> Builder { + self.options.disable_name_namespacing = true; + self + } + }, + as_args: "--disable-name-namespacing", + }, + /// Whether we should avoid generating nested `struct` names. + disable_nested_struct_naming: bool { + methods: { + /// Disable nested `struct` naming. + /// + /// The following `struct`s have different names for C and C++. In C, they are visible + /// as `foo` and `bar`. In C++, they are visible as `foo` and `foo::bar`. + /// + /// ```c + /// struct foo { + /// struct bar { + /// } b; + /// }; + /// ``` + /// + /// `bindgen` tries to avoid duplicate names by default, so it follows the C++ naming + /// convention and it generates `foo` and `foo_bar` instead of just `foo` and `bar`. + /// + /// This method disables this behavior and it is indented to be used only for headers + /// that were written in C. + pub fn disable_nested_struct_naming(mut self) -> Builder { + self.options.disable_nested_struct_naming = true; + self + } + }, + as_args: "--disable-nested-struct-naming", + }, + /// Whether we should avoid embedding version identifiers into source code. + disable_header_comment: bool { + methods: { + /// Do not insert the `bindgen` version identifier into the generated bindings. + /// + /// This identifier is inserted by default. + pub fn disable_header_comment(mut self) -> Self { + self.options.disable_header_comment = true; + self + } + + }, + as_args: "--disable-header-comment", + }, + /// Whether we should generate layout tests for generated `struct`s. + layout_tests: bool { + default: true, + methods: { + /// Set whether layout tests should be generated. + /// + /// Layout tests are generated by default. + pub fn layout_tests(mut self, doit: bool) -> Self { + self.options.layout_tests = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-layout-tests"), + }, + /// Whether we should implement `Debug` for types that cannot derive it. + impl_debug: bool { + methods: { + /// Set whether `Debug` should be implemented for types that cannot derive it. + /// + /// This option is disabled by default. + pub fn impl_debug(mut self, doit: bool) -> Self { + self.options.impl_debug = doit; + self + } + + }, + as_args: "--impl-debug", + }, + /// Whether we should implement `PartialEq` types that cannot derive it. + impl_partialeq: bool { + methods: { + /// Set whether `PartialEq` should be implemented for types that cannot derive it. + /// + /// This option is disabled by default. + pub fn impl_partialeq(mut self, doit: bool) -> Self { + self.options.impl_partialeq = doit; + self + } + }, + as_args: "--impl-partialeq", + }, + /// Whether we should derive `Copy` when possible. + derive_copy: bool { + default: true, + methods: { + /// Set whether the `Copy` trait should be derived when possible. + /// + /// `Copy` is derived by default. + pub fn derive_copy(mut self, doit: bool) -> Self { + self.options.derive_copy = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-derive-copy"), + }, + + /// Whether we should derive `Debug` when possible. + derive_debug: bool { + default: true, + methods: { + /// Set whether the `Debug` trait should be derived when possible. + /// + /// The [`Builder::impl_debug`] method can be used to implement `Debug` for types that + /// cannot derive it. + /// + /// `Debug` is derived by default. + pub fn derive_debug(mut self, doit: bool) -> Self { + self.options.derive_debug = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-derive-debug"), + }, + + /// Whether we should derive `Default` when possible. + derive_default: bool { + methods: { + /// Set whether the `Default` trait should be derived when possible. + /// + /// `Default` is not derived by default. + pub fn derive_default(mut self, doit: bool) -> Self { + self.options.derive_default = doit; + self + } + }, + as_args: |&value, args| { + let arg = if value { + "--with-derive-default" + } else { + "--no-derive-default" + }; + + args.push(arg.to_owned()); + }, + }, + /// Whether we should derive `Hash` when possible. + derive_hash: bool { + methods: { + /// Set whether the `Hash` trait should be derived when possible. + /// + /// `Hash` is not derived by default. + pub fn derive_hash(mut self, doit: bool) -> Self { + self.options.derive_hash = doit; + self + } + }, + as_args: "--with-derive-hash", + }, + /// Whether we should derive `PartialOrd` when possible. + derive_partialord: bool { + methods: { + /// Set whether the `PartialOrd` trait should be derived when possible. + /// + /// Take into account that `Ord` cannot be derived for a type that does not implement + /// `PartialOrd`. For this reason, setting this method to `false` also sets + /// automatically [`Builder::derive_ord`] to `false`. + /// + /// `PartialOrd` is not derived by default. + pub fn derive_partialord(mut self, doit: bool) -> Self { + self.options.derive_partialord = doit; + if !doit { + self.options.derive_ord = false; + } + self + } + }, + as_args: "--with-derive-partialord", + }, + /// Whether we should derive `Ord` when possible. + derive_ord: bool { + methods: { + /// Set whether the `Ord` trait should be derived when possible. + /// + /// Take into account that `Ord` cannot be derived for a type that does not implement + /// `PartialOrd`. For this reason, the value set with this method will also be set + /// automatically for [`Builder::derive_partialord`]. + /// + /// `Ord` is not derived by default. + pub fn derive_ord(mut self, doit: bool) -> Self { + self.options.derive_ord = doit; + self.options.derive_partialord = doit; + self + } + }, + as_args: "--with-derive-ord", + }, + /// Whether we should derive `PartialEq` when possible. + derive_partialeq: bool { + methods: { + /// Set whether the `PartialEq` trait should be derived when possible. + /// + /// Take into account that `Eq` cannot be derived for a type that does not implement + /// `PartialEq`. For this reason, setting this method to `false` also sets + /// automatically [`Builder::derive_eq`] to `false`. + /// + /// The [`Builder::impl_partialeq`] method can be used to implement `PartialEq` for + /// types that cannot derive it. + /// + /// `PartialEq` is not derived by default. + pub fn derive_partialeq(mut self, doit: bool) -> Self { + self.options.derive_partialeq = doit; + if !doit { + self.options.derive_eq = false; + } + self + } + }, + as_args: "--with-derive-partialeq", + }, + /// Whether we should derive `Eq` when possible. + derive_eq: bool { + methods: { + /// Set whether the `Eq` trait should be derived when possible. + /// + /// Take into account that `Eq` cannot be derived for a type that does not implement + /// `PartialEq`. For this reason, the value set with this method will also be set + /// automatically for [`Builder::derive_partialeq`]. + /// + /// `Eq` is not derived by default. + pub fn derive_eq(mut self, doit: bool) -> Self { + self.options.derive_eq = doit; + if doit { + self.options.derive_partialeq = doit; + } + self + } + }, + as_args: "--with-derive-eq", + }, + /// Whether we should use `core` instead of `std`. + /// + /// If this option is enabled and the Rust target version is greater than 1.64, the prefix for + /// C platform-specific types will be `::core::ffi` instead of `::core::os::raw`. + use_core: bool { + methods: { + /// Use `core` instead of `std` in the generated bindings. + /// + /// `std` is used by default. + pub fn use_core(mut self) -> Builder { + self.options.use_core = true; + self + } + + }, + as_args: "--use-core", + }, + /// An optional prefix for the C platform-specific types. + ctypes_prefix: Option { + methods: { + /// Use the given prefix for the C platform-specific types instead of `::std::os::raw`. + /// + /// Alternatively, the [`Builder::use_core`] method can be used to set the prefix to + /// `::core::ffi` or `::core::os::raw`. + pub fn ctypes_prefix>(mut self, prefix: T) -> Builder { + self.options.ctypes_prefix = Some(prefix.into()); + self + } + }, + as_args: "--ctypes-prefix", + }, + /// The prefix for anonymous fields. + anon_fields_prefix: String { + default: DEFAULT_ANON_FIELDS_PREFIX.into(), + methods: { + /// Use the given prefix for the anonymous fields. + /// + /// An anonymous field, is a field of a C/C++ type that does not have a name. For + /// example, in the following C code: + /// ```c + /// struct integer { + /// struct { + /// int inner; + /// }; + /// } + /// ``` + /// + /// The only field of the `integer` `struct` is an anonymous field and its Rust + /// representation will be named using this prefix followed by an integer identifier. + /// + /// The default prefix is `__bindgen_anon_`. + pub fn anon_fields_prefix>(mut self, prefix: T) -> Builder { + self.options.anon_fields_prefix = prefix.into(); + self + } + }, + as_args: |prefix, args| { + if prefix != DEFAULT_ANON_FIELDS_PREFIX { + args.push("--anon-fields-prefix".to_owned()); + args.push(prefix.clone()); + } + }, + }, + /// Whether to measure the time for each one of the `bindgen` phases. + time_phases: bool { + methods: { + /// Set whether to measure the elapsed time for each one of the `bindgen` phases. This + /// information is printed to `stderr`. + /// + /// The elapsed time is not measured by default. + pub fn time_phases(mut self, doit: bool) -> Self { + self.options.time_phases = doit; + self + } + }, + as_args: "--time-phases", + }, + /// Whether to convert C float types to `f32` and `f64`. + convert_floats: bool { + default: true, + methods: { + /// Avoid converting C float types to `f32` and `f64`. + pub fn no_convert_floats(mut self) -> Self { + self.options.convert_floats = false; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-convert-floats"), + }, + /// The set of raw lines to be prepended to the top-level module of the generated Rust code. + raw_lines: Vec> { + methods: { + /// Add a line of Rust code at the beginning of the generated bindings. The string is + /// passed through without any modification. + pub fn raw_line>(mut self, arg: T) -> Self { + self.options.raw_lines.push(arg.into().into_boxed_str()); + self + } + }, + as_args: |raw_lines, args| { + for line in raw_lines { + args.push("--raw-line".to_owned()); + args.push(line.clone().into()); + } + }, + }, + /// The set of raw lines to prepend to different modules. + module_lines: HashMap, Vec>> { + methods: { + /// Add a given line to the beginning of a given module. + /// + /// This option only comes into effect if the [`Builder::enable_cxx_namespaces`] method + /// is also being called. + pub fn module_raw_line(mut self, module: T, line: U) -> Self + where + T: Into, + U: Into, + { + self.options + .module_lines + .entry(module.into().into_boxed_str()) + .or_default() + .push(line.into().into_boxed_str()); + self + } + }, + as_args: |module_lines, args| { + for (module, lines) in module_lines { + for line in lines { + args.push("--module-raw-line".to_owned()); + args.push(module.clone().into()); + args.push(line.clone().into()); + } + } + }, + }, + /// The input header files. + input_headers: Vec> { + methods: { + /// Add an input C/C++ header to generate bindings for. + /// + /// This can be used to generate bindings for a single header: + /// + /// ```ignore + /// let bindings = bindgen::Builder::default() + /// .header("input.h") + /// .generate() + /// .unwrap(); + /// ``` + /// + /// Or for multiple headers: + /// + /// ```ignore + /// let bindings = bindgen::Builder::default() + /// .header("first.h") + /// .header("second.h") + /// .header("third.h") + /// .generate() + /// .unwrap(); + /// ``` + pub fn header>(mut self, header: T) -> Builder { + self.options.input_headers.push(header.into().into_boxed_str()); + self + } + + /// Add input C/C++ header(s) to generate bindings for. + /// + /// This can be used to generate bindings for a single header: + /// + /// ```ignore + /// let bindings = bindgen::Builder::default() + /// .headers(["input.h"]) + /// .generate() + /// .unwrap(); + /// ``` + /// + /// Or for multiple headers: + /// + /// ```ignore + /// let bindings = bindgen::Builder::default() + /// .headers(["first.h", "second.h", "third.h"]) + /// .generate() + /// .unwrap(); + /// ``` + pub fn headers(mut self, headers: I) -> Builder + where + I::Item: Into, + { + self.options + .input_headers + .extend(headers.into_iter().map(Into::into).map(Into::into)); + self + } + }, + // This field is handled specially inside the macro. + as_args: ignore, + }, + /// The set of arguments to be passed straight through to Clang. + clang_args: Vec> { + methods: { + /// Add an argument to be passed straight through to Clang. + pub fn clang_arg>(self, arg: T) -> Builder { + self.clang_args([arg.into().into_boxed_str()]) + } + + /// Add several arguments to be passed straight through to Clang. + pub fn clang_args(mut self, args: I) -> Builder + where + I::Item: AsRef, + { + for arg in args { + self.options.clang_args.push(arg.as_ref().to_owned().into_boxed_str()); + } + self + } + }, + // This field is handled specially inside the macro. + as_args: ignore, + }, + /// The set of arguments to be passed straight through to Clang for the macro fallback code. + fallback_clang_args: Vec> { + methods: {}, + as_args: ignore, + }, + /// Tuples of unsaved file contents of the form (name, contents). + input_header_contents: Vec<(Box, Box)> { + methods: { + /// Add `contents` as an input C/C++ header named `name`. + /// + /// This can be used to inject additional C/C++ code as an input without having to + /// create additional header files. + pub fn header_contents(mut self, name: &str, contents: &str) -> Builder { + // Apparently clang relies on having virtual FS correspondent to + // the real one, so we need absolute paths here + let absolute_path = env::current_dir() + .expect("Cannot retrieve current directory") + .join(name) + .to_str() + .expect("Cannot convert current directory name to string") + .into(); + self.options + .input_header_contents + .push((absolute_path, contents.into())); + self + } + }, + // Header contents cannot be added from the CLI. + as_args: ignore, + }, + /// A user-provided visitor to allow customizing different kinds of situations. + parse_callbacks: Vec> { + methods: { + /// Add a new [`ParseCallbacks`] instance to configure types in different situations. + /// + /// This can also be used with [`CargoCallbacks`](struct@crate::CargoCallbacks) to emit + /// `cargo:rerun-if-changed=...` for all `#include`d header files. + pub fn parse_callbacks(mut self, cb: Box) -> Self { + self.options.parse_callbacks.push(Rc::from(cb)); + self + } + }, + as_args: |_callbacks, _args| { + #[cfg(feature = "__cli")] + for cb in _callbacks { + _args.extend(cb.cli_args()); + } + }, + }, + /// Which kind of items should we generate. We generate all of them by default. + codegen_config: CodegenConfig { + default: CodegenConfig::all(), + methods: { + /// Do not generate any functions. + /// + /// Functions are generated by default. + pub fn ignore_functions(mut self) -> Builder { + self.options.codegen_config.remove(CodegenConfig::FUNCTIONS); + self + } + + /// Do not generate any methods. + /// + /// Methods are generated by default. + pub fn ignore_methods(mut self) -> Builder { + self.options.codegen_config.remove(CodegenConfig::METHODS); + self + } + + /// Choose what to generate using a [`CodegenConfig`]. + /// + /// This option overlaps with [`Builder::ignore_functions`] and + /// [`Builder::ignore_methods`]. + /// + /// All the items in `CodegenConfig` are generated by default. + pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self { + self.options.codegen_config = config; + self + } + }, + as_args: |codegen_config, args| { + if !codegen_config.functions() { + args.push("--ignore-functions".to_owned()); + } + + args.push("--generate".to_owned()); + + //Temporary placeholder for the 4 options below. + let mut options: Vec = Vec::new(); + if codegen_config.functions() { + options.push("functions".to_owned()); + } + + if codegen_config.types() { + options.push("types".to_owned()); + } + + if codegen_config.vars() { + options.push("vars".to_owned()); + } + + if codegen_config.methods() { + options.push("methods".to_owned()); + } + + if codegen_config.constructors() { + options.push("constructors".to_owned()); + } + + if codegen_config.destructors() { + options.push("destructors".to_owned()); + } + + args.push(options.join(",")); + + if !codegen_config.methods() { + args.push("--ignore-methods".to_owned()); + } + }, + }, + /// Whether to treat inline namespaces conservatively. + conservative_inline_namespaces: bool { + methods: { + /// Treat inline namespaces conservatively. + /// + /// This is tricky, because in C++ is technically legal to override an item + /// defined in an inline namespace: + /// + /// ```cpp + /// inline namespace foo { + /// using Bar = int; + /// } + /// using Bar = long; + /// ``` + /// + /// Even though referencing `Bar` is a compiler error. + /// + /// We want to support this (arguably esoteric) use case, but we do not want to make + /// the rest of `bindgen` users pay an usability penalty for that. + /// + /// To support this, we need to keep all the inline namespaces around, but then using + /// `bindgen` becomes a bit more difficult, because you cannot reference paths like + /// `std::string` (you'd need to use the proper inline namespace). + /// + /// We could complicate a lot of the logic to detect name collisions and, in the + /// absence of collisions, generate a `pub use inline_ns::*` or something like that. + /// + /// That is probably something we can do to improve the usability of this option if we + /// realize it is needed way more often. Our guess is that this extra logic is not + /// going to be very useful. + /// + /// This option is disabled by default. + pub fn conservative_inline_namespaces(mut self) -> Builder { + self.options.conservative_inline_namespaces = true; + self + } + }, + as_args: "--conservative-inline-namespaces", + }, + /// Whether to keep documentation comments in the generated output. + generate_comments: bool { + default: true, + methods: { + /// Set whether the generated bindings should contain documentation comments. + /// + /// Documentation comments are included by default. + /// + /// Note that clang excludes comments from system headers by default, pass + /// `"-fretain-comments-from-system-headers"` to the [`Builder::clang_arg`] method to + /// include them. + /// + /// It is also possible to process all comments and not just documentation using the + /// `"-fparse-all-comments"` flag. Check [these slides on clang comment parsing]( + /// https://llvm.org/devmtg/2012-11/Gribenko_CommentParsing.pdf) for more information + /// and examples. + pub fn generate_comments(mut self, doit: bool) -> Self { + self.options.generate_comments = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-doc-comments"), + }, + /// Whether to generate [`NonNull`] pointers for C++ references. + /// + /// [`NonNull`]: core::ptr::NonNull + generate_cxx_nonnull_references: bool { + default: false, + methods: { + /// Generate `NonNull` pointers in place of raw pointers for C++ + /// references. + /// + /// This option is disabled by default: + /// + /// Enabling it erases information about constness in generated + /// code, and `NonNull` is more cumbersome to use than raw pointers. + pub fn generate_cxx_nonnull_references(mut self, doit: bool) -> Self { + self.options.generate_cxx_nonnull_references = doit; + self + } + }, + as_args: |value, args| value.as_args(args, "--nonnull-references"), + }, + /// Whether to generate inline functions. + generate_inline_functions: bool { + methods: { + /// Set whether to generate inline functions. + /// + /// This option is disabled by default. + /// + /// Note that they will usually not work. However you can use `-fkeep-inline-functions` + /// or `-fno-inline-functions` if you are responsible of compiling the library to make + /// them callable. + /// + /// Check the [`Builder::wrap_static_fns`] method for an alternative. + pub fn generate_inline_functions(mut self, doit: bool) -> Self { + self.options.generate_inline_functions = doit; + self + } + }, + as_args: "--generate-inline-functions", + }, + /// Whether to allowlist types recursively. + allowlist_recursively: bool { + default: true, + methods: { + /// Set whether to recursively allowlist items. + /// + /// Items are allowlisted recursively by default. + /// + /// Given that we have explicitly allowlisted the `initiate_dance_party` function in + /// this C header: + /// + /// ```c + /// typedef struct MoonBoots { + /// int bouncy_level; + /// } MoonBoots; + /// + /// void initiate_dance_party(MoonBoots* boots); + /// ``` + /// + /// We would normally generate bindings to both the `initiate_dance_party` function and + /// the `MoonBoots` type that it transitively references. If `false` is passed to this + /// method, `bindgen` will not emit bindings for anything except the explicitly + /// allowlisted items, meaning that the definition for `MoonBoots` would not be + /// generated. However, the `initiate_dance_party` function would still reference + /// `MoonBoots`! + /// + /// **Disabling this feature will almost certainly cause `bindgen` to emit bindings + /// that will not compile!** If you disable this feature, then it is *your* + /// responsibility to provide definitions for every type that is referenced from an + /// explicitly allowlisted item. One way to provide the missing definitions is by using + /// the [`Builder::raw_line`] method, another would be to define them in Rust and then + /// `include!(...)` the bindings immediately afterwards. + pub fn allowlist_recursively(mut self, doit: bool) -> Self { + self.options.allowlist_recursively = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-recursive-allowlist"), + }, + /// Whether to emit `#[macro_use] extern crate objc;` instead of `use objc;` in the prologue of + /// the files generated from objective-c files. + objc_extern_crate: bool { + methods: { + /// Emit `#[macro_use] extern crate objc;` instead of `use objc;` in the prologue of + /// the files generated from objective-c files. + /// + /// `use objc;` is emitted by default. + pub fn objc_extern_crate(mut self, doit: bool) -> Self { + self.options.objc_extern_crate = doit; + self + } + }, + as_args: "--objc-extern-crate", + }, + /// Whether to generate proper block signatures instead of `void` pointers. + generate_block: bool { + methods: { + /// Generate proper block signatures instead of `void` pointers. + /// + /// `void` pointers are used by default. + pub fn generate_block(mut self, doit: bool) -> Self { + self.options.generate_block = doit; + self + } + }, + as_args: "--generate-block", + }, + /// Whether to generate strings as `CStr`. + generate_cstr: bool { + methods: { + /// Set whether string constants should be generated as `&CStr` instead of `&[u8]`. + /// + /// A minimum Rust target of 1.59 is required for this to have any effect as support + /// for `CStr::from_bytes_with_nul_unchecked` in `const` contexts is needed. + /// + /// This option is disabled by default but will become enabled by default in a future + /// release, so enabling this is recommended. + pub fn generate_cstr(mut self, doit: bool) -> Self { + self.options.generate_cstr = doit; + self + } + }, + as_args: "--generate-cstr", + }, + /// Whether to emit `#[macro_use] extern crate block;` instead of `use block;` in the prologue + /// of the files generated from apple block files. + block_extern_crate: bool { + methods: { + /// Emit `#[macro_use] extern crate block;` instead of `use block;` in the prologue of + /// the files generated from apple block files. + /// + /// `use block;` is emitted by default. + pub fn block_extern_crate(mut self, doit: bool) -> Self { + self.options.block_extern_crate = doit; + self + } + }, + as_args: "--block-extern-crate", + }, + /// Whether to use the clang-provided name mangling. + enable_mangling: bool { + default: true, + methods: { + /// Set whether to use the clang-provided name mangling. This is probably needed for + /// C++ features. + /// + /// The mangling provided by clang is used by default. + /// + /// We allow disabling this option because some old `libclang` versions seem to return + /// incorrect results in some cases for non-mangled functions, check [#528] for more + /// information. + /// + /// [#528]: https://github.com/rust-lang/rust-bindgen/issues/528 + pub fn trust_clang_mangling(mut self, doit: bool) -> Self { + self.options.enable_mangling = doit; + self + } + + }, + as_args: |value, args| (!value).as_args(args, "--distrust-clang-mangling"), + }, + /// Whether to detect include paths using `clang_sys`. + detect_include_paths: bool { + default: true, + methods: { + /// Set whether to detect include paths using `clang_sys`. + /// + /// `clang_sys` is used to detect include paths by default. + pub fn detect_include_paths(mut self, doit: bool) -> Self { + self.options.detect_include_paths = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-include-path-detection"), + }, + /// Whether we should try to fit macro constants into types smaller than `u32` and `i32`. + fit_macro_constants: bool { + methods: { + /// Set whether `bindgen` should try to fit macro constants into types smaller than `u32` + /// and `i32`. + /// + /// This option is disabled by default. + pub fn fit_macro_constants(mut self, doit: bool) -> Self { + self.options.fit_macro_constants = doit; + self + } + }, + as_args: "--fit-macro-constant-types", + }, + /// Whether to prepend the `enum` name to constant or newtype variants. + prepend_enum_name: bool { + default: true, + methods: { + /// Set whether to prepend the `enum` name to constant or newtype variants. + /// + /// The `enum` name is prepended by default. + pub fn prepend_enum_name(mut self, doit: bool) -> Self { + self.options.prepend_enum_name = doit; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-prepend-enum-name"), + }, + /// Version of the Rust compiler to target. + rust_target: RustTarget { + methods: { + /// Specify the Rust target version. + /// + /// The default target is the latest stable Rust version. + pub fn rust_target(mut self, rust_target: RustTarget) -> Self { + self.options.set_rust_target(rust_target); + self + } + }, + as_args: |rust_target, args| { + args.push("--rust-target".to_owned()); + args.push(rust_target.to_string()); + }, + }, + /// The Rust edition to use for code generation. + rust_edition: Option { + methods: { + /// Specify the Rust target edition. + /// + /// The default edition is the latest edition supported by the chosen Rust target. + pub fn rust_edition(mut self, rust_edition: RustEdition) -> Self { + self.options.rust_edition = Some(rust_edition); + self + } + } + as_args: |edition, args| { + if let Some(edition) = edition { + args.push("--rust-edition".to_owned()); + args.push(edition.to_string()); + } + }, + }, + /// Features to be enabled. They are derived from `rust_target`. + rust_features: RustFeatures { + methods: {}, + // This field cannot be set from the CLI, + as_args: ignore, + }, + /// Enable support for native Rust unions if they are supported. + untagged_union: bool { + default: true, + methods: { + /// Disable support for native Rust unions, if supported. + /// + /// The default value of this option is set based on the value passed to + /// [`Builder::rust_target`]. + pub fn disable_untagged_union(mut self) -> Self { + self.options.untagged_union = false; + self + } + } + as_args: |value, args| (!value).as_args(args, "--disable-untagged-union"), + }, + /// Whether we should record which items in the regex sets did match any C items. + record_matches: bool { + default: true, + methods: { + /// Set whether we should record which items in our regex sets did match any C items. + /// + /// Matches are recorded by default. + pub fn record_matches(mut self, doit: bool) -> Self { + self.options.record_matches = doit; + self + } + + }, + as_args: |value, args| (!value).as_args(args, "--no-record-matches"), + }, + /// Whether `size_t` should be translated to `usize` automatically. + size_t_is_usize: bool { + default: true, + methods: { + /// Set whether `size_t` should be translated to `usize`. + /// + /// If `size_t` is translated to `usize`, type definitions for `size_t` will not be + /// emitted. + /// + /// `size_t` is translated to `usize` by default. + pub fn size_t_is_usize(mut self, is: bool) -> Self { + self.options.size_t_is_usize = is; + self + } + }, + as_args: |value, args| (!value).as_args(args, "--no-size_t-is-usize"), + }, + /// The tool that should be used to format the generated bindings. + formatter: Formatter { + methods: { + /// Set whether `rustfmt` should be used to format the generated bindings. + /// + /// `rustfmt` is used by default. + /// + /// This method overlaps in functionality with the more general [`Builder::formatter`]. + /// Thus, the latter should be preferred. + #[deprecated] + pub fn rustfmt_bindings(mut self, doit: bool) -> Self { + self.options.formatter = if doit { + Formatter::Rustfmt + } else { + Formatter::None + }; + self + } + + /// Set which tool should be used to format the generated bindings. + /// + /// The default formatter is [`Formatter::Rustfmt`]. + /// + /// To be able to use `prettyplease` as a formatter, the `"prettyplease"` feature for + /// `bindgen` must be enabled in the Cargo manifest. + pub fn formatter(mut self, formatter: Formatter) -> Self { + self.options.formatter = formatter; + self + } + }, + as_args: |formatter, args| { + if *formatter != Default::default() { + args.push("--formatter".to_owned()); + args.push(formatter.to_string()); + } + }, + }, + /// The absolute path to the `rustfmt` configuration file. + rustfmt_configuration_file: Option { + methods: { + /// Set the absolute path to the `rustfmt` configuration file. + /// + /// The default `rustfmt` options are used if `None` is passed to this method or if + /// this method is not called at all. + /// + /// Calling this method will set the [`Builder::rustfmt_bindings`] option to `true` + /// and the [`Builder::formatter`] option to [`Formatter::Rustfmt`]. + pub fn rustfmt_configuration_file(mut self, path: Option) -> Self { + self = self.formatter(Formatter::Rustfmt); + self.options.rustfmt_configuration_file = path; + self + } + }, + as_args: "--rustfmt-configuration-file", + }, + /// Types that should not derive `PartialEq`. + no_partialeq_types: RegexSet { + methods: { + regex_option! { + /// Do not derive `PartialEq` for a given type. + pub fn no_partialeq>(mut self, arg: T) -> Builder { + self.options.no_partialeq_types.insert(arg.into()); + self + } + } + }, + as_args: "--no-partialeq", + }, + /// Types that should not derive `Copy`. + no_copy_types: RegexSet { + methods: { + regex_option! { + /// Do not derive `Copy` and `Clone` for a given type. + pub fn no_copy>(mut self, arg: T) -> Self { + self.options.no_copy_types.insert(arg.into()); + self + } + } + }, + as_args: "--no-copy", + }, + /// Types that should not derive `Debug`. + no_debug_types: RegexSet { + methods: { + regex_option! { + /// Do not derive `Debug` for a given type. + pub fn no_debug>(mut self, arg: T) -> Self { + self.options.no_debug_types.insert(arg.into()); + self + } + } + }, + as_args: "--no-debug", + }, + /// Types that should not derive or implement `Default`. + no_default_types: RegexSet { + methods: { + regex_option! { + /// Do not derive or implement `Default` for a given type. + pub fn no_default>(mut self, arg: T) -> Self { + self.options.no_default_types.insert(arg.into()); + self + } + } + }, + as_args: "--no-default", + }, + /// Types that should not derive `Hash`. + no_hash_types: RegexSet { + methods: { + regex_option! { + /// Do not derive `Hash` for a given type. + pub fn no_hash>(mut self, arg: T) -> Builder { + self.options.no_hash_types.insert(arg.into()); + self + } + } + }, + as_args: "--no-hash", + }, + /// Types that should be annotated with `#[must_use]`. + must_use_types: RegexSet { + methods: { + regex_option! { + /// Annotate the given type with the `#[must_use]` attribute. + pub fn must_use_type>(mut self, arg: T) -> Builder { + self.options.must_use_types.insert(arg.into()); + self + } + } + }, + as_args: "--must-use-type", + }, + /// Whether C arrays should be regular pointers in rust or array pointers + array_pointers_in_arguments: bool { + methods: { + /// Translate arrays `T arr[size]` into array pointers `*mut [T; size]` instead of + /// translating them as `*mut T` which is the default. + /// + /// The same is done for `*const` pointers. + pub fn array_pointers_in_arguments(mut self, doit: bool) -> Self { + self.options.array_pointers_in_arguments = doit; + self + } + + }, + as_args: "--use-array-pointers-in-arguments", + }, + /// Attributes to add to all `extern` blocks. + extern_fn_block_attrs: Vec { + methods: { + /// Add an attribute to all the `extern` blocks generated by `bindgen`. + /// + /// This can be used to add attributes such as `#[link(...)]` to all + /// the `extern` blocks. + pub fn extern_fn_block_attrs>(mut self, attr: T) -> Self { + self.options.extern_fn_block_attrs.push(attr.into()); + self + } + }, + as_args: |attrs, args| { + for attr in attrs { + args.push("--extern-fn-block-attrs".to_owned()); + args.push(attr.clone()); + } + }, + }, + /// The name of the `wasm_import_module`. + wasm_import_module_name: Option { + methods: { + /// Adds the `#[link(wasm_import_module = import_name)]` attribute to all the `extern` + /// blocks generated by `bindgen`. + /// + /// This attribute is not added by default. + pub fn wasm_import_module_name>( + mut self, + import_name: T, + ) -> Self { + self.options.extern_fn_block_attrs.push(format!( + "#[link(wasm_import_module = \"{}\")]", import_name.into() + )); + self + } + }, + as_args: "--wasm-import-module-name", + }, + /// The name of the dynamic library (if we are generating bindings for a shared library). + dynamic_library_name: Option { + methods: { + /// Generate bindings for a shared library with the given name. + /// + /// This option is disabled by default. + pub fn dynamic_library_name>( + mut self, + dynamic_library_name: T, + ) -> Self { + self.options.dynamic_library_name = Some(dynamic_library_name.into()); + self + } + }, + as_args: "--dynamic-loading", + }, + /// Whether to require successful linkage for all routines in a shared library. + dynamic_link_require_all: bool { + methods: { + /// Set whether to require successful linkage for all routines in a shared library. + /// This allows us to optimize function calls by being able to safely assume function + /// pointers are valid. + /// + /// This option only comes into effect if the [`Builder::dynamic_library_name`] option + /// is set. + /// + /// This option is disabled by default. + pub fn dynamic_link_require_all(mut self, req: bool) -> Self { + self.options.dynamic_link_require_all = req; + self + } + }, + as_args: "--dynamic-link-require-all", + }, + /// Whether to only make generated bindings `pub` if the items would be publicly accessible by + /// C++. + respect_cxx_access_specs: bool { + methods: { + /// Set whether to respect the C++ access specifications. + /// + /// Passing `true` to this method will set the visibility of the generated Rust items + /// as `pub` only if the corresponding C++ items are publicly accessible instead of + /// marking all the items as public, which is the default. + pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self { + self.options.respect_cxx_access_specs = doit; + self + } + + }, + as_args: "--respect-cxx-access-specs", + }, + /// Whether to translate `enum` integer types to native Rust integer types. + translate_enum_integer_types: bool { + methods: { + /// Set whether to always translate `enum` integer types to native Rust integer types. + /// + /// Passing `true` to this method will result in `enum`s having types such as `u32` and + /// `i16` instead of `c_uint` and `c_short` which is the default. The `#[repr]` types + /// of Rust `enum`s are always translated to Rust integer types. + pub fn translate_enum_integer_types(mut self, doit: bool) -> Self { + self.options.translate_enum_integer_types = doit; + self + } + }, + as_args: "--translate-enum-integer-types", + }, + /// Whether to generate types with C style naming. + c_naming: bool { + methods: { + /// Set whether to generate types with C style naming. + /// + /// Passing `true` to this method will add prefixes to the generated type names. For + /// example, instead of a `struct` with name `A` we will generate a `struct` with + /// `struct_A`. Currently applies to `struct`s, `union`s, and `enum`s. + pub fn c_naming(mut self, doit: bool) -> Self { + self.options.c_naming = doit; + self + } + }, + as_args: "--c-naming", + }, + /// Whether to always emit explicit padding fields. + force_explicit_padding: bool { + methods: { + /// Set whether to always emit explicit padding fields. + /// + /// This option should be enabled if a `struct` needs to be serialized in its native + /// format (padding bytes and all). This could be required if such `struct` will be + /// written to a file or sent over the network, as anything reading the padding bytes + /// of a struct may cause undefined behavior. + /// + /// Padding fields are not emitted by default. + pub fn explicit_padding(mut self, doit: bool) -> Self { + self.options.force_explicit_padding = doit; + self + } + }, + as_args: "--explicit-padding", + }, + /// Whether to emit vtable functions. + vtable_generation: bool { + methods: { + /// Set whether to enable experimental support to generate virtual table functions. + /// + /// This option should mostly work, though some edge cases are likely to be broken. + /// + /// Virtual table generation is disabled by default. + pub fn vtable_generation(mut self, doit: bool) -> Self { + self.options.vtable_generation = doit; + self + } + }, + as_args: "--vtable-generation", + }, + /// Whether to sort the generated Rust items. + sort_semantically: bool { + methods: { + /// Set whether to sort the generated Rust items in a predefined manner. + /// + /// Items are not ordered by default. + pub fn sort_semantically(mut self, doit: bool) -> Self { + self.options.sort_semantically = doit; + self + } + }, + as_args: "--sort-semantically", + }, + /// Whether to deduplicate `extern` blocks. + merge_extern_blocks: bool { + methods: { + /// Merge all extern blocks under the same module into a single one. + /// + /// Extern blocks are not merged by default. + pub fn merge_extern_blocks(mut self, doit: bool) -> Self { + self.options.merge_extern_blocks = doit; + self + } + }, + as_args: "--merge-extern-blocks", + }, + /// Whether to wrap unsafe operations in unsafe blocks. + wrap_unsafe_ops: bool { + methods: { + /// Wrap all unsafe operations in unsafe blocks. + /// + /// Unsafe operations are not wrapped by default. + pub fn wrap_unsafe_ops(mut self, doit: bool) -> Self { + self.options.wrap_unsafe_ops = doit; + self + } + }, + as_args: "--wrap-unsafe-ops", + }, + /// Use DSTs to represent structures with flexible array members. + flexarray_dst: bool { + methods: { + /// Use DSTs to represent structures with flexible array members. + /// + /// This option is disabled by default. + pub fn flexarray_dst(mut self, doit: bool) -> Self { + self.options.flexarray_dst = doit; + self + } + }, + as_args: "--flexarray-dst", + }, + /// Patterns for functions whose ABI should be overridden. + abi_overrides: HashMap { + methods: { + regex_option! { + /// Override the ABI of a given function. + pub fn override_abi>(mut self, abi: Abi, arg: T) -> Self { + self.options + .abi_overrides + .entry(abi) + .or_default() + .insert(arg.into()); + self + } + } + }, + as_args: |overrides, args| { + for (abi, set) in overrides { + for item in set.get_items() { + args.push("--override-abi".to_owned()); + args.push(format!("{item}={abi}")); + } + } + }, + }, + /// Whether to generate wrappers for `static` functions. + wrap_static_fns: bool { + methods: { + /// Set whether to generate wrappers for `static` functions. + /// + /// Passing `true` to this method will generate a C source file with non-`static` + /// functions that call the `static` functions found in the input headers and can be + /// called from Rust once the source file is compiled. + /// + /// The path of this source file can be set using the [`Builder::wrap_static_fns_path`] + /// method. + pub fn wrap_static_fns(mut self, doit: bool) -> Self { + self.options.wrap_static_fns = doit; + self + } + }, + as_args: "--wrap-static-fns", + }, + /// The suffix to be added to the function wrappers for `static` functions. + wrap_static_fns_suffix: Option { + methods: { + /// Set the suffix added to the wrappers for `static` functions. + /// + /// This option only comes into effect if `true` is passed to the + /// [`Builder::wrap_static_fns`] method. + /// + /// The default suffix is `__extern`. + pub fn wrap_static_fns_suffix>(mut self, suffix: T) -> Self { + self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned()); + self + } + }, + as_args: "--wrap-static-fns-suffix", + }, + /// The path of the file where the wrappers for `static` functions will be emitted. + wrap_static_fns_path: Option { + methods: { + /// Set the path for the source code file that would be created if any wrapper + /// functions must be generated due to the presence of `static` functions. + /// + /// `bindgen` will automatically add the right extension to the header and source code + /// files. + /// + /// This option only comes into effect if `true` is passed to the + /// [`Builder::wrap_static_fns`] method. + /// + /// The default path is `temp_dir/bindgen/extern`, where `temp_dir` is the path + /// returned by [`std::env::temp_dir`] . + pub fn wrap_static_fns_path>(mut self, path: T) -> Self { + self.options.wrap_static_fns_path = Some(path.as_ref().to_owned()); + self + } + }, + as_args: "--wrap-static-fns-path", + }, + /// Default visibility of fields. + default_visibility: FieldVisibilityKind { + methods: { + /// Set the default visibility of fields, including bitfields and accessor methods for + /// bitfields. + /// + /// This option only comes into effect if the [`Builder::respect_cxx_access_specs`] + /// option is disabled. + pub fn default_visibility( + mut self, + visibility: FieldVisibilityKind, + ) -> Self { + self.options.default_visibility = visibility; + self + } + }, + as_args: |visibility, args| { + if *visibility != Default::default() { + args.push("--default-visibility".to_owned()); + args.push(visibility.to_string()); + } + }, + }, + /// Whether to emit diagnostics or not. + emit_diagnostics: bool { + methods: { + #[cfg(feature = "experimental")] + /// Emit diagnostics. + /// + /// These diagnostics are emitted to `stderr` if you are using `bindgen-cli` or printed + /// using `cargo:warning=` if you are using `bindgen` as a `build-dependency`. + /// + /// Diagnostics are not emitted by default. + /// + /// The layout and contents of these diagnostic messages are not covered by versioning + /// and can change without notice. + pub fn emit_diagnostics(mut self) -> Self { + self.options.emit_diagnostics = true; + self + } + }, + as_args: "--emit-diagnostics", + }, + /// Whether to use Clang evaluation on temporary files as a fallback for macros that fail to + /// parse. + clang_macro_fallback: bool { + methods: { + /// Use Clang as a fallback for macros that fail to parse using `CExpr`. + /// + /// This uses a workaround to evaluate each macro in a temporary file. Because this + /// results in slower compilation, this option is opt-in. + pub fn clang_macro_fallback(mut self) -> Self { + self.options.clang_macro_fallback = true; + self + } + }, + as_args: "--clang-macro-fallback", + } + /// Path to use for temporary files created by clang macro fallback code like precompiled + /// headers. + clang_macro_fallback_build_dir: Option { + methods: { + /// Set a path to a directory to which `.c` and `.h.pch` files should be written for the + /// purpose of using clang to evaluate macros that can't be easily parsed. + /// + /// The default location for `.h.pch` files is the directory that the corresponding + /// `.h` file is located in. The default for the temporary `.c` file used for clang + /// parsing is the current working directory. Both of these defaults are overridden + /// by this option. + pub fn clang_macro_fallback_build_dir>(mut self, path: P) -> Self { + self.options.clang_macro_fallback_build_dir = Some(path.as_ref().to_owned()); + self + } + }, + as_args: "--clang-macro-fallback-build-dir", + } + /// Whether to always report C++ "deleted" functions. + generate_deleted_functions: bool { + methods: { + /// Set whether to generate C++ functions even marked "=deleted" + /// + /// Although not useful to call these functions, downstream code + /// generators may need to know whether they've been deleted in + /// order to determine the relocatability of a C++ type + /// (specifically by virtue of which constructors exist.) + pub fn generate_deleted_functions(mut self, doit: bool) -> Self { + self.options.generate_deleted_functions = doit; + self + } + + }, + as_args: "--generate-deleted-functions", + }, + /// Whether to always report C++ "pure virtual" functions. + generate_pure_virtual_functions: bool { + methods: { + /// Set whether to generate C++ functions that are pure virtual. + /// + /// These functions can't be called, so the only reason + /// to generate them is if downstream postprocessors + /// need to know of their existence. This is necessary, + /// for instance, to determine whether a type itself is + /// pure virtual and thus can't be allocated. + /// Downstream code generators may choose to make code to + /// allow types to be allocated but need to avoid doing so + /// if the type contains pure virtual functions. + pub fn generate_pure_virtual_functions(mut self, doit: bool) -> Self { + self.options.generate_pure_virtual_functions = doit; + self + } + + }, + as_args: "--generate-pure-virtual-functions", + }, + /// Whether to always report C++ "private" functions. + generate_private_functions: bool { + methods: { + /// Set whether to generate C++ functions that are private. + /// + /// These functions can't be called, so the only reason + /// to generate them is if downstream postprocessors + /// need to know of their existence. + pub fn generate_private_functions(mut self, doit: bool) -> Self { + self.options.generate_private_functions = doit; + self + } + + }, + as_args: "--generate-private-functions", + }, +} diff --git a/bindgen/parse.rs b/bindgen/parse.rs new file mode 100644 index 0000000000..d29b090fcb --- /dev/null +++ b/bindgen/parse.rs @@ -0,0 +1,41 @@ +//! Common traits and types related to parsing our IR from Clang cursors. +#![deny(clippy::missing_docs_in_private_items)] + +use crate::clang; +use crate::ir::context::{BindgenContext, ItemId}; + +/// Not so much an error in the traditional sense, but a control flow message +/// when walking over Clang's AST with a cursor. +#[derive(Debug)] +pub(crate) enum ParseError { + /// Recurse down the current AST node's children. + Recurse, + /// Continue on to the next sibling AST node, or back up to the parent's + /// siblings if we've exhausted all of this node's siblings (and so on). + Continue, +} + +/// The result of parsing a Clang AST node. +#[derive(Debug)] +pub(crate) enum ParseResult { + /// We've already resolved this item before, here is the extant `ItemId` for + /// it. + AlreadyResolved(ItemId), + + /// This is a newly parsed item. If the cursor is `Some`, it points to the + /// AST node where the new `T` was declared. + New(T, Option), +} + +/// An intermediate representation "sub-item" (i.e. one of the types contained +/// inside an `ItemKind` variant) that can be parsed from a Clang cursor. +pub(crate) trait ClangSubItemParser: Sized { + /// Attempt to parse this type from the given cursor. + /// + /// The fact that is a reference guarantees it's held by the context, and + /// allow returning already existing types. + fn parse( + cursor: clang::Cursor, + context: &mut BindgenContext, + ) -> Result, ParseError>; +} diff --git a/bindgen/regex_set.rs b/bindgen/regex_set.rs new file mode 100644 index 0000000000..32279557b5 --- /dev/null +++ b/bindgen/regex_set.rs @@ -0,0 +1,199 @@ +//! A type that represents the union of a set of regular expressions. +#![deny(clippy::missing_docs_in_private_items)] + +use regex::RegexSet as RxSet; +use std::cell::Cell; + +/// A dynamic set of regular expressions. +#[derive(Clone, Debug, Default)] +pub(crate) struct RegexSet { + items: Vec>, + /// Whether any of the items in the set was ever matched. The length of this + /// vector is exactly the length of `items`. + matched: Vec>, + set: Option, + /// Whether we should record matching items in the `matched` vector or not. + record_matches: bool, +} + +impl RegexSet { + /// Is this set empty? + pub(crate) fn is_empty(&self) -> bool { + self.items.is_empty() + } + + /// Insert a new regex into this set. + pub(crate) fn insert(&mut self, string: S) + where + S: AsRef, + { + self.items.push(string.as_ref().to_owned().into_boxed_str()); + self.matched.push(Cell::new(false)); + self.set = None; + } + + /// Returns slice of String from its field 'items' + pub(crate) fn get_items(&self) -> &[Box] { + &self.items + } + + /// Returns an iterator over regexes in the set which didn't match any + /// strings yet. + pub(crate) fn unmatched_items(&self) -> impl Iterator { + self.items.iter().enumerate().filter_map(move |(i, item)| { + if !self.record_matches || self.matched[i].get() { + return None; + } + + Some(item.as_ref()) + }) + } + + /// Construct a `RegexSet` from the set of entries we've accumulated. + /// + /// Must be called before calling `matches()`, or it will always return + /// false. + #[inline] + #[allow(unused)] + pub(crate) fn build(&mut self, record_matches: bool) { + self.build_inner(record_matches, None); + } + + #[cfg(all(feature = "__cli", feature = "experimental"))] + /// Construct a `RegexSet` from the set of entries we've accumulated and emit diagnostics if the + /// name of the regex set is passed to it. + /// + /// Must be called before calling `matches()`, or it will always return + /// false. + #[inline] + pub(crate) fn build_with_diagnostics( + &mut self, + record_matches: bool, + name: Option<&'static str>, + ) { + self.build_inner(record_matches, name); + } + + #[cfg(all(not(feature = "__cli"), feature = "experimental"))] + /// Construct a RegexSet from the set of entries we've accumulated and emit diagnostics if the + /// name of the regex set is passed to it. + /// + /// Must be called before calling `matches()`, or it will always return + /// false. + #[inline] + pub(crate) fn build_with_diagnostics( + &mut self, + record_matches: bool, + name: Option<&'static str>, + ) { + self.build_inner(record_matches, name); + } + + fn build_inner( + &mut self, + record_matches: bool, + _name: Option<&'static str>, + ) { + let items = self.items.iter().map(|item| format!("^({item})$")); + self.record_matches = record_matches; + self.set = match RxSet::new(items) { + Ok(x) => Some(x), + Err(e) => { + warn!("Invalid regex in {:?}: {e:?}", self.items); + #[cfg(feature = "experimental")] + if let Some(name) = _name { + invalid_regex_warning(self, e, name); + } + None + } + } + } + + /// Does the given `string` match any of the regexes in this set? + pub(crate) fn matches(&self, string: S) -> bool + where + S: AsRef, + { + let s = string.as_ref(); + let Some(ref set) = self.set else { + return false; + }; + + if !self.record_matches { + return set.is_match(s); + } + + let matches = set.matches(s); + if !matches.matched_any() { + return false; + } + for i in &matches { + self.matched[i].set(true); + } + + true + } +} + +#[cfg(feature = "experimental")] +fn invalid_regex_warning( + set: &RegexSet, + err: regex::Error, + name: &'static str, +) { + use crate::diagnostics::{Diagnostic, Level, Slice}; + + let mut diagnostic = Diagnostic::default(); + + match err { + regex::Error::Syntax(string) => { + if string.starts_with("regex parse error:\n") { + let mut source = String::new(); + + let mut parsing_source = true; + + for line in string.lines().skip(1) { + if parsing_source { + if line.starts_with(' ') { + source.push_str(line); + source.push('\n'); + continue; + } + parsing_source = false; + } + let error = "error: "; + if line.starts_with(error) { + let (_, msg) = line.split_at(error.len()); + diagnostic.add_annotation(msg.to_owned(), Level::Error); + } else { + diagnostic.add_annotation(line.to_owned(), Level::Info); + } + } + let mut slice = Slice::default(); + slice.with_source(source); + diagnostic.add_slice(slice); + + diagnostic.with_title( + "Error while parsing a regular expression.", + Level::Warning, + ); + } else { + diagnostic.with_title(string, Level::Warning); + } + } + err => { + let err = err.to_string(); + diagnostic.with_title(err, Level::Warning); + } + } + + diagnostic.add_annotation( + format!("This regular expression was passed via `{name}`."), + Level::Note, + ); + + if set.items.iter().any(|item| item.as_ref() == "*") { + diagnostic.add_annotation("Wildcard patterns \"*\" are no longer considered valid. Use \".*\" instead.", Level::Help); + } + diagnostic.display(); +} diff --git a/bindgen/time.rs b/bindgen/time.rs new file mode 100644 index 0000000000..2952e36f76 --- /dev/null +++ b/bindgen/time.rs @@ -0,0 +1,52 @@ +use std::io::{self, Write}; +use std::time::{Duration, Instant}; + +/// RAII timer to measure how long phases take. +#[derive(Debug)] +pub struct Timer<'a> { + output: bool, + name: &'a str, + start: Instant, +} + +impl<'a> Timer<'a> { + /// Creates a Timer with the given name, and starts it. By default, + /// will print to stderr when it is `drop`'d + pub fn new(name: &'a str) -> Self { + Timer { + output: true, + name, + start: Instant::now(), + } + } + + /// Sets whether or not the Timer will print a message + /// when it is dropped. + pub fn with_output(mut self, output: bool) -> Self { + self.output = output; + self + } + + /// Returns the time elapsed since the timer's creation + pub fn elapsed(&self) -> Duration { + self.start.elapsed() + } + + fn print_elapsed(&mut self) { + if self.output { + let elapsed = self.elapsed(); + let time = (elapsed.as_secs() as f64) * 1e3 + + f64::from(elapsed.subsec_nanos()) / 1e6; + let stderr = io::stderr(); + // Arbitrary output format, subject to change. + writeln!(stderr.lock(), " time: {time:>9.3} ms.\t{}", self.name) + .expect("timer write should not fail"); + } + } +} + +impl Drop for Timer<'_> { + fn drop(&mut self) { + self.print_elapsed(); + } +} diff --git a/book/book.toml b/book/book.toml index e94e304621..3f55b78377 100644 --- a/book/book.toml +++ b/book/book.toml @@ -1,3 +1,8 @@ -title = "The `bindgen` User Guide" -author = "The Servo project developers" +[book] +title = "The bindgen User Guide" description = "`bindgen` automatically generates Rust FFI bindings to C and C++ libraries." + +[output.html] +git-repository-url = "https://github.com/rust-lang/rust-bindgen" +edit-url-template = "https://github.com/rust-lang/rust-bindgen/edit/main/book/{path}" +search.use-boolean-and = true diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 81a21fea8e..ac57aaad64 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -8,16 +8,24 @@ - [Create a `wrapper.h` Header](./tutorial-2.md) - [Create a `build.rs` File](./tutorial-3.md) - [Include the Generated Bindings in `src/lib.rs`](./tutorial-4.md) - - [Write a Sanity Test](./tutorial-5.md) + - [Write a Smoke Test](./tutorial-5.md) - [Publish Your Crate!](./tutorial-6.md) + - [Bindings for Non-System Libraries](./non-system-libraries.md) - [Command Line Usage](./command-line-usage.md) - [Customizing the Generated Bindings](./customizing-generated-bindings.md) - - [Whitelisting](./whitelisting.md) - - [Blacklisting](./blacklisting.md) + - [Allowlisting](./allowlisting.md) + - [Blocklisting](./blocklisting.md) - [Treating a Type as an Opaque Blob of Bytes](./opaque.md) - [Replacing One Type with Another](./replacing-types.md) - [Preventing the Derivation of `Copy` and `Clone`](./nocopy.md) + - [Preventing the Derivation of `Debug`](./nodebug.md) + - [Preventing the Derivation of `Default`](./nodefault.md) + - [Annotating Types with `#[must-use]`](./must-use-types.md) + - [Field Visibility](./visibility.md) + - [Code Formatting](./code-formatting.md) - [Generating Bindings to C++](./cpp.md) +- [Generating Bindings to Objective-C](./objc.md) - [Using Unions](./using-unions.md) - [Using Bitfields](./using-bitfields.md) +- [Using Flexible Array Members](./using-fam.md) - [FAQ](./faq.md) diff --git a/book/src/allowlisting.md b/book/src/allowlisting.md new file mode 100644 index 0000000000..99dd169865 --- /dev/null +++ b/book/src/allowlisting.md @@ -0,0 +1,35 @@ +# Allowlisting + +Allowlisting allows us to be precise about which type, function, and global +variable definitions `bindgen` generates bindings for. By default, if we don't +specify any allowlisting rules, everything is considered allowlisted. This may +not be desirable because of either + +* the generated bindings contain a lot of extra definitions we don't plan on using, or +* the header file contains C++ features for which Rust does not have a + corresponding form (such as partial template specialization), and we would + like to avoid these definitions + +If we specify allowlisting rules, then `bindgen` will only generate bindings to +types, functions, and global variables that match the allowlisting rules, or are +transitively used by a definition that matches them. + +### Library + +* [`bindgen::Builder::allowlist_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_type) +* [`bindgen::Builder::allowlist_function`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_function) +* [`bindgen::Builder::allowlist_var`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_var) +* [`bindgen::Builder::allowlist_file`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_file) +* [`bindgen::Builder::allowlist_item`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_item) + +### Command Line + +* `--allowlist-type ` +* `--allowlist-function ` +* `--allowlist-var ` +* `--allowlist-file ` +* `--allowlist-item ` + +### Annotations + +None. diff --git a/book/src/blacklisting.md b/book/src/blacklisting.md deleted file mode 100644 index 8d4ee163bf..0000000000 --- a/book/src/blacklisting.md +++ /dev/null @@ -1,30 +0,0 @@ -# Blacklisting - -If you need to provide your own custom translation of some type (for example, -because you need to wrap one of its fields in an `UnsafeCell`), you can -explicitly blacklist generation of its definition. Uses of the blacklisted type -will still appear in other types' definitions. (If you don't want the type to -appear in the bindings at -all, [make it opaque](./opaque.html) instead of -blacklisting it.) - -Blacklisted types are pessimistically assumed not to be able to `derive` any -traits, which can transitively affect other types' ability to `derive` traits or -not. - -### Library - -* [`bindgen::Builder::blacklist_type`](https://docs.rs/bindgen/0.31.3/bindgen/struct.Builder.html#method.blacklist_type) - -### Command Line - -* `--blacklist-type ` - -### Annotations - -```cpp -///
-class Foo { - // ... -}; -``` diff --git a/book/src/blocklisting.md b/book/src/blocklisting.md new file mode 100644 index 0000000000..535a08c8d5 --- /dev/null +++ b/book/src/blocklisting.md @@ -0,0 +1,43 @@ +# Blocklisting + +If you need to provide your own custom translation of some type (for example, +because you need to wrap one of its fields in an `UnsafeCell`), you can +explicitly blocklist generation of its definition. Uses of the blocklisted type +will still appear in other types' definitions. (If you don't want the type to +appear in the bindings at +all, [make it opaque](./opaque.md) instead of +blocklisting it.) + +Blocklisted types are pessimistically assumed not to be able to `derive` any +traits, which can transitively affect other types' ability to `derive` traits or +not. + +The `blocklist-file` option also allows the blocklisting of all items from a +particular path regex, for example to block all types defined in system headers +that are transitively included. + +### Library + +* [`bindgen::Builder::blocklist_file`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_file) +* [`bindgen::Builder::blocklist_function`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_function) +* [`bindgen::Builder::blocklist_item`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_item) +* [`bindgen::Builder::blocklist_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_type) +* [`bindgen::Builder::blocklist_var`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_var) + +### Command Line + +* `--blocklist-file ` +* `--blocklist-function ` +* `--blocklist-item ` +* `--blocklist-type ` +* `--blocklist-var ` + + +### Annotations + +```cpp +///
+class Foo { + // ... +}; +``` diff --git a/book/src/chapter_1.md b/book/src/chapter_1.md deleted file mode 100644 index b743fda354..0000000000 --- a/book/src/chapter_1.md +++ /dev/null @@ -1 +0,0 @@ -# Chapter 1 diff --git a/book/src/code-formatting.md b/book/src/code-formatting.md new file mode 100644 index 0000000000..368535c452 --- /dev/null +++ b/book/src/code-formatting.md @@ -0,0 +1,103 @@ +# Code Formatting + +`bindgen` uses `rustfmt` to format the emitted bindings. This section describes +how to adjust the `rustfmt` behavior when being used from `bindgen`. + +## Passing a `rustfmt.toml` configuration file + +`rustfmt` should automatically use any `rustfmt.toml` file that is present in +the directory from where `bindgen` will be run. If you want to use a +configuration file that has a different name or that is in a different +directory you can use the `--rustfmt-configuration-file` flag or the +[`Builder::rustfmt_configuration_file`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.rustfmt_configuration_file) +method. + +## Using a nightly release of `rustfmt` + +If the `rustfmt` command does not correspond to a nightly release of `rustfmt` +but you have `rustup` available, you can use `nightly` by following these +steps: + +### When using `bindgen` as a CLI application + +Use `rustup run` to run `bindgen`: + +```bash +$ rustup run nightly bindgen [ARGS] +``` + +### When using `bindgen` as a library + +Take the output of the following command: +```bash +$ rustup which rustfmt --toolchain=nightly +``` +and pass it to +[`Builder::with_rustfmt`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.with_rustfmt): + +```rust,ignore +use bindgen::Builder; +use std::process::Command; + +fn main() { + let output = Command::new("rustup") + .args(["which", "rustfmt", "--toolchain", "nightly"]) + .output() + .expect("Could not spawn `rustup` command"); + + assert!( + output.status.success(), + "Unsuccessful status code when running `rustup`: {output:?}", + ); + + let rustfmt_path = + String::from_utf8(output.stdout).expect("The `rustfmt` path is not valid `utf-8`"); + + let bindings = Builder::default() + .header("path/to/input.h") + .with_rustfmt(rustfmt_path) + .generate() + .expect("Could not generate bindings"); + + bindings + .write_to_file("path/to/output.rs") + .expect("Could not write bindings"); +} +``` + +These two methods also apply to any other toolchain available in your system. + +## Using `prettyplease` + +The [`prettyplease`](https://github.com/dtolnay/prettyplease) crate is a +minimal formatter for generated code. To format bindings using `prettyplease` +you have to invoke `bindgen` with either the `--formatter=prettyplease` flag or +the `bindgen::Builder::formatter(bindgen::Formatter::Prettyplease)`. One of +its advantages is that `prettyplease` can be used in minimal environments where +the Rust toolchain is not installed. + +## How can I normalize `#[doc]` attributes? + +`bindgen` emits all the documentation using `#[doc]` attributes by default. If +you want to use the more user-friendly `///` syntax, you have two options: + +### Use `rustfmt` + +`rustfmt` can be configured to normalize documentation. To do so, you have to +create a `rustfmt.toml` file with the following contents: + +```toml +normalize_doc_attributes = true +``` + +Then, you have set up `bindgen` so it passes this file to `rustfmt`. Given that +the `normalize_doc_attributes` option is +[unstable](https://github.com/rust-lang/rustfmt/issues/3351), you also have to +set up bindgen to use a `nightly` release of `rustfmt`. + + +### Use `prettyplease` + +`prettyplease` normalizes documentation without any additional configuration. +Then you just have to tell `bindgen` to use `prettyplease` as the code +formatter. diff --git a/book/src/command-line-usage.md b/book/src/command-line-usage.md index d90eb442b8..051a63efad 100644 --- a/book/src/command-line-usage.md +++ b/book/src/command-line-usage.md @@ -3,7 +3,7 @@ Install the `bindgen` executable with `cargo`: ```bash -$ cargo install bindgen +$ cargo install bindgen-cli ``` The `bindgen` executable is installed to `~/.cargo/bin`. You have to add that @@ -13,7 +13,7 @@ directory to your `$PATH` to use `bindgen`. output file path for the generated bindings. If the output file path is not supplied, the bindings are printed to `stdout`. -If we wanted to generated Rust FFI bindings from a C header named `input.h` and +If we wanted to generate Rust FFI bindings from a C header named `input.h` and put them in the `bindings.rs` file, we would invoke `bindgen` like this: ```bash diff --git a/book/src/cpp.md b/book/src/cpp.md index 0324901676..22e9dcf120 100644 --- a/book/src/cpp.md +++ b/book/src/cpp.md @@ -1,29 +1,29 @@ # Generating Bindings to C++ -`bindgen` can handle a some C++ features, but not all of them. To set +`bindgen` can handle some C++ features, but not all of them. To set expectations: `bindgen` will give you the type definitions and FFI declarations you need to build an API to the C++ library, but using those types in Rust will be nowhere near as nice as using them in C++. You will have to manually call constructors, destructors, overloaded operators, etc yourself. When passing in header files, the file will automatically be treated as C++ if -it ends in `.hpp`. If it doesn't, adding `-x c++` clang args can be used to +it ends in `.hpp`. If it doesn't, adding `clang_args(["-x", "c++"])` can be used to force C++ mode. You probably also want to use `-std=c++14` or similar clang args as well. -You pretty much **must** use [whitelisting](./whitelisting.html) when working -with C++ to avoid pulling in all of the `std::*` types, many of which `bindgen` +You pretty much **must** use [allowlisting](./allowlisting.md) when working +with C++ to avoid pulling in all of the `std::.*` types, many of which `bindgen` cannot handle. Additionally, you may want to mark other types as -[opaque](./opaque.html) that `bindgen` stumbles on. It is recommended to mark -all of `std::*` opaque, and to whitelist only precisely the functions and types +[opaque](./opaque.md) that `bindgen` stumbles on. It is recommended to mark +all of `std::.*` opaque, and to allowlist only precisely the functions and types you intend to use. -You should read up on the [FAQs](./faq.html) as well. +You should read up on the [FAQs](./faq.md) as well. ## Supported Features * Inheritance (for the most part; there are - [some outstanding bugs](https://github.com/rust-lang-nursery/rust-bindgen/issues/380)) + [some outstanding bugs](https://github.com/rust-lang/rust-bindgen/issues/380)) * Methods @@ -50,7 +50,7 @@ Without further ado, here are C++ features that `bindgen` does not support or cannot translate into Rust: * Inline functions and methods: see -["Why isn't `bindgen` generating bindings to inline functions?"](./faq.html#why-isnt-bindgen-generating-bindings-to-inline-functions) +["Why isn't `bindgen` generating bindings to inline functions?"](./faq.md#why-isnt-bindgen-generating-bindings-to-inline-functions) * Template functions, methods of template classes and structs. We don't know which monomorphizations exist, and can't create new ones because we aren't a @@ -59,7 +59,7 @@ cannot translate into Rust: * Anything related to template specialization: * Partial template specialization * Traits templates - * Specialization Failure Is Not An Error (SFINAE) + * Substitution Failure Is Not An Error (SFINAE) * Cross language inheritance, for example inheriting from a Rust struct in C++. @@ -69,5 +69,91 @@ cannot translate into Rust: * Exceptions: if a function called through a `bindgen`-generated interface raises an exception that is not caught by the function itself, this will generate undefined behaviour. See - [the tracking issue for exceptions](https://github.com/rust-lang-nursery/rust-bindgen/issues/1208) + [the tracking issue for exceptions](https://github.com/rust-lang/rust-bindgen/issues/1208) for more details. + +* Many C++ specific aspects of calling conventions. For example in the Itanium abi types that are + "[non trivial for the purposes of calls](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial)" + should be passed by pointer, even if they are otherwise eligible to be passed in a register. + Similarly in both the Itanium and MSVC ABIs such types are returned by "hidden parameter", much like + large structs in C that would not fit into a register. This also applies to types with any base classes + in the MSVC ABI (see [x64 calling convention](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#return-values)). + Because bindgen does not know about these rules generated interfaces using such types are currently invalid. + +## Constructor semantics + +`bindgen` will generate a wrapper for any class constructor declared in the +input headers. For example, this headers file + +```c++ +class MyClass { + public: + MyClass(); + void method(); +}; +``` + +Will produce the following code: +```rust,ignore +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MyClass { + pub _address: u8, +} +extern "C" { + #[link_name = "\u{1}_ZN7MyClass6methodEv"] + pub fn MyClass_method(this: *mut MyClass); +} +extern "C" { + #[link_name = "\u{1}_ZN7MyClassC1Ev"] + pub fn MyClass_MyClass(this: *mut MyClass); +} +impl MyClass { + #[inline] + pub unsafe fn method(&mut self) { + MyClass_method(self) + } + #[inline] + pub unsafe fn new() -> Self { + let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); + MyClass_MyClass(__bindgen_tmp.as_mut_ptr()); + __bindgen_tmp.assume_init() + } +} +``` +This `MyClass::new` Rust method can be used as a substitute for the `MyClass` +C++ constructor. However, the address of the value from inside the method will +be different than from the outside. This is because the `__bindgen_tmp` value +is moved when the `MyClass::new` method returns. + +In contrast, the C++ constructor will not move the value, meaning that the +address of the value will be the same inside and outside the constructor. +If the original C++ relies on this semantic difference somehow, you should use the +`MyClass_MyClass` binding directly instead of the `MyClass::new` method. + +In other words, the Rust equivalent for the following C++ code + +```c++ +MyClass instance = MyClass(); +instance.method(); +``` + +is not this + +```rust,ignore +let instance = MyClass::new(); +instance.method(); +``` + +but this + +```rust,ignore +let instance = std::mem::MaybeUninit::::uninit(); +MyClass_MyClass(instance.as_mut_ptr()); +instance.assume_init_mut().method(); +``` + +You can easily verify this fact if you provide a implementation for `MyClass` +and `method` that prints the `this` pointer address. However, you can +ignore this fact if you know that the original C++ code does not rely on the +instance address in its internal logic. diff --git a/book/src/faq.md b/book/src/faq.md index 4f4bd8204b..59699ac757 100644 --- a/book/src/faq.md +++ b/book/src/faq.md @@ -3,14 +3,16 @@ - -- [Why isn't `bindgen` generating methods for this whitelisted class?](#why-isnt-bindgen-generating-methods-for-this-whitelisted-class) +- [Why isn't `bindgen` generating methods for this allowlisted class?](#why-isnt-bindgen-generating-methods-for-this-allowlisted-class) - [Why isn't `bindgen` generating bindings to inline functions?](#why-isnt-bindgen-generating-bindings-to-inline-functions) - [Does `bindgen` support the C++ Standard Template Library (STL)?](#does-bindgen-support-the-c-standard-template-library-stl) +- [How to deal with bindgen generated padding fields?](#how-to-deal-with-bindgen-generated-padding-fields) +- [How to generate bindings for a custom target?](#how-to-generate-bindings-for-a-custom-target) +- [Why isn't `bindgen` generating documentation for system headers?](#why-isnt-bindgen-generating-documentation-for-system-headers) -### Why isn't `bindgen` generating methods for this whitelisted class? +### Why isn't `bindgen` generating methods for this allowlisted class? Are the methods `inline` methods, or defined inline in the class? For example: @@ -45,13 +47,20 @@ creates linking errors. However, if you are compiling the C/C++ yourself (rather than using a system shared library, for example), then you can pass `-fkeep-inline-functions` or `-fno-inline-functions` to `gcc` or `clang`, and invoke `bindgen` with either -the `bindgen::Builder::generate_inline_functions` method or the -`--generate-inline-functions` flag. +the [`bindgen::Builder::generate_inline_functions`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.generate_inline_functions) +method or the `--generate-inline-functions` flag. Note that these functions and methods are usually marked inline for a reason: they tend to be hot. The above workaround makes them an out-of-line call, which might not provide acceptable performance. +As an alternative, you can invoke `bindgen` with either the +[`bindgen::Builder::wrap_static_fns`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.wrap_static_fns) +method or the `--wrap-static-fns` flag. That generates a C source file that can +be compiled against the input headers to produce Rust bindings for `static` and +`static inline` functions. See [How to handle `static inline` functions](https://github.com/rust-lang/rust-bindgen/discussions/2405) +for further information. + ### Does `bindgen` support the C++ Standard Template Library (STL)? Sort of. A little. Depends what you mean by "support". @@ -62,5 +71,54 @@ STL. That ties our hands when it comes to linking: ["Why isn't `bindgen` generat As far as generating opaque blobs of bytes with the correct size and alignment, `bindgen` can do pretty well. This is typically enough to let you use types that transitively contain STL things. We generally recommend marking `std::.*` as -opaque, and then whitelisting only the specific things you need from the library +opaque, and then allowlisting only the specific things you need from the library you're binding to that is pulling in STL headers. + +### How to deal with bindgen generated padding fields? + +Depending the architecture, toolchain versions and source struct, it is +possible that bindgen will generate padding fields named `__bindgen_padding_N`. +As these fields might be present when compiling for one architecture but not +for an other, you should not initialize these fields manually when initializing +the struct. Instead, use the `Default` trait. You can either enable this when +constructing the `Builder` using the [`derive_default`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default) +method, or you can implement this per struct using: + +```rust,ignore +impl Default for SRC_DATA { + fn default() -> Self { + unsafe { std::mem::zeroed() } + } +} +``` + +This makes it possible to initialize `SRC_DATA` by: + +```rust,ignore +SRC_DATA { + field_a: "foo", + field_b: "bar", + ..Default::default() +} +``` + +In the case bindgen generates a padding field, then this field will +be automatically initialized by `..Default::default()`. + +### How to generate bindings for a custom target? + +To generate bindings for a custom target you only need to pass the [`--target`](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-target) +argument to `libclang`. For example, if you want to generate bindings for the +`armv7a-none-eabi` target using the command line, you need to invoke `bindgen` +like so: +```bash +$ bindgen -- --target=armv7a-none-eabi +``` +If you are using `bindgen` as a library, you should call +`builder.clang_arg("--target=armv7a-none-eabi")` on your `builder`. + +### Why isn't `bindgen` generating documentation for system headers? + +By default, Bindgen does not generate documentation for system headers because +`libclang` does not provide this information. To address this, you should call +`builder.clang_arg("-fretain-comments-from-system-headers")` on your `builder`. diff --git a/book/src/introduction.md b/book/src/introduction.md index f39e0da0c7..e77ea0c69e 100644 --- a/book/src/introduction.md +++ b/book/src/introduction.md @@ -1,6 +1,6 @@ # Introduction -**[`bindgen`](https://github.com/rust-lang-nursery/rust-bindgen) automatically generates Rust +**[`bindgen`](https://github.com/rust-lang/rust-bindgen) automatically generates Rust FFI bindings to C and C++ libraries.** For example, given the C header `cool.h`: @@ -18,7 +18,7 @@ void cool_function(int i, char c, CoolStruct* cs); functions and use its types: ```rust -/* automatically generated by rust-bindgen */ +/* automatically generated by rust-bindgen 0.99.9 */ #[repr(C)] pub struct CoolStruct { diff --git a/book/src/must-use-types.md b/book/src/must-use-types.md new file mode 100644 index 0000000000..1792e5a485 --- /dev/null +++ b/book/src/must-use-types.md @@ -0,0 +1,29 @@ +# Annotating Types with `#[must-use]` + +`bindgen` can be instructed to annotate certain types with +[`#[must_use]`](https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute). + +Some libraries have a common error type, returned by many of their functions, +which needs to be checked after every call. In these cases it's useful to add +`#[must_use]` to this type, so the Rust compiler emits a warning when the check +is missing. + +### Library + +* [`bindgen::Builder::must_use_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.must_use_type) + +### Command Line + +* `--must-use-type ` + +### Annotations + +```c +/**
*/ +struct ErrorType { + // ... +}; + +... +``` + diff --git a/book/src/nocopy.md b/book/src/nocopy.md index ec21f3ae7e..e0d17ed0cb 100644 --- a/book/src/nocopy.md +++ b/book/src/nocopy.md @@ -4,14 +4,17 @@ basis. Sometimes, it might not understand that although adding `#[derive(Copy, Clone)]` to a translated type definition will compile, it still shouldn't do that for reasons it can't know. In these cases, the `nocopy` annotation can be -used to prevent bindgen to autoderive the `Copy` and `Clone` traits for a type. +used to prevent bindgen from automatically deriving the `Copy` and `Clone` +traits for a type. ### Library -* [`bindgen::Builder::no_copy`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.no_copy) +* [`bindgen::Builder::derive_copy`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_copy) +* [`bindgen::Builder::no_copy`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_copy) ### Command Line +* `--no-derive-copy` * `--no-copy ` ### Annotations diff --git a/book/src/nodebug.md b/book/src/nodebug.md new file mode 100644 index 0000000000..4fa820134b --- /dev/null +++ b/book/src/nodebug.md @@ -0,0 +1,42 @@ +# Preventing the Derivation of `Debug` + +`bindgen` will attempt to derive the `Debug` traits on a best-effort +basis. Sometimes, it might not understand that although adding `#[derive(Debug)]` to a translated type definition will compile, it still shouldn't do +that for reasons it can't know. In these cases, the `nodebug` annotation can be +used to prevent bindgen from automatically deriving the `Debug` trait for a type. + +### Library + +* [`bindgen::Builder::derive_debug`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_debug) +* [`bindgen::Builder::no_debug`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_debug) + +### Command Line + +* `--no-derive-debug` +* `--no-debug ` + +### Annotations + +```c +/** + * Although bindgen can't know, this enum is not safe to format the output. + * the value may be combined with multiple bits in many C/C++ cases, + * for example: + * + *
+ */ +enum AVRounding { + AV_ROUND_ZERO = 0, + AV_ROUND_INF = 1, + AV_ROUND_DOWN = 2, + AV_ROUND_UP = 3, + AV_ROUND_NEAR_INF = 5, + AV_ROUND_PASS_MINMAX = 8192, +}; + +// Prototype +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; + +// Call +int64_t pts = av_rescale_rnd(40000, 3600, 90000, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); +``` diff --git a/book/src/nodefault.md b/book/src/nodefault.md new file mode 100644 index 0000000000..9561d7c17f --- /dev/null +++ b/book/src/nodefault.md @@ -0,0 +1,52 @@ +# Preventing the Derivation of `Default` + +By default, `Default` is not derived. + +`bindgen` will attempt to derive/impl the `Default` traits on a best-effort basis. +Sometimes, we need customize the implementation of `Default` for certain types. +In these cases, the `nodefault` annotation can be used to prevent bindgen from +automatically deriving the `Default` trait for a type. + +### Library + +* [`bindgen::Builder::derive_default`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default) +* [`bindgen::Builder::no_default`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_default) + +### Command Line + +* `--with-derive-default` +* `--no-default ` + +### Annotations + +```c +/** + * We need to specify some preset values as the Default of Header. + * + * for example: + * + *
+ */ +struct Header { + unsigned int magic; + unsigned char data[252]; +}; + +... +``` + +### Customize Implements + +```rust,ignore +// Include the generated bindings. +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +impl Default for Header { + fn default() -> Self { + Self { + magic: 0x10203040u32, + data: [0; 252usize], + } + } +} +``` diff --git a/book/src/non-system-libraries.md b/book/src/non-system-libraries.md new file mode 100644 index 0000000000..598889d360 --- /dev/null +++ b/book/src/non-system-libraries.md @@ -0,0 +1,99 @@ +Now let's suppose we want to generate bindings for a non-system library. We +will be the same crate setup as the previous tutorial. First let's create a new +directory `hello` with two files inside it. A C source file `hello.c` +containing +```c +int hello() { + return 42; +} +``` +and a C header file `hello.h` containing +```c +int hello(); +``` + +Given that the library has not been compiled yet, we need to modify the +`build.rs` build script to compile the `hello.c` source file into a static +library: + +```rust,ignore +use std::env; +use std::path::PathBuf; + +fn main() { + // This is the directory where the `c` library is located. + let libdir_path = PathBuf::from("hello") + // Canonicalize the path as `rustc-link-search` requires an absolute + // path. + .canonicalize() + .expect("cannot canonicalize path"); + + // This is the path to the `c` headers file. + let headers_path = libdir_path.join("hello.h"); + let headers_path_str = headers_path.to_str().expect("Path is not a valid string"); + + // This is the path to the intermediate object file for our library. + let obj_path = libdir_path.join("hello.o"); + // This is the path to the static library file. + let lib_path = libdir_path.join("libhello.a"); + + // Tell cargo to look for shared libraries in the specified directory + println!("cargo:rustc-link-search={}", libdir_path.to_str().unwrap()); + + // Tell cargo to tell rustc to link our `hello` library. Cargo will + // automatically know it must look for a `libhello.a` file. + println!("cargo:rustc-link-lib=hello"); + + // Run `clang` to compile the `hello.c` file into a `hello.o` object file. + // Unwrap if it is not possible to spawn the process. + if !std::process::Command::new("clang") + .arg("-c") + .arg("-o") + .arg(&obj_path) + .arg(libdir_path.join("hello.c")) + .output() + .expect("could not spawn `clang`") + .status + .success() + { + // Panic if the command was not successful. + panic!("could not compile object file"); + } + + // Run `ar` to generate the `libhello.a` file from the `hello.o` file. + // Unwrap if it is not possible to spawn the process. + if !std::process::Command::new("ar") + .arg("rcs") + .arg(lib_path) + .arg(obj_path) + .output() + .expect("could not spawn `ar`") + .status + .success() + { + // Panic if the command was not successful. + panic!("could not emit library file"); + } + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header(headers_path_str) + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("bindings.rs"); + bindings + .write_to_file(out_path) + .expect("Couldn't write bindings!"); +} +``` diff --git a/book/src/objc.md b/book/src/objc.md new file mode 100644 index 0000000000..3845ed5a2e --- /dev/null +++ b/book/src/objc.md @@ -0,0 +1,76 @@ +# Generating Bindings to Objective-C + +`bindgen` does not (yet) have full Objective-C support, but it can generate +bindings for many of the Apple frameworks without too much blocklisting. + +In order to generate bindings, you will need `-x objective-c` as a clang arg. If +you'd like to use [block](https://crates.io/crates/block) you will need +`-fblocks` as a clang arg as well. + +Depending on your setup, you may need `--generate-block` to generate the block +function aliases and `--block-extern-crate` to insert a `extern crate block` at +the beginning of the generated bindings. The same logic applies to the +`--objc-extern-crate` parameter. + +The Objective-C classes will be represented as a `struct Foo(id)` and a trait +`IFoo` where `Foo` is the Objective-C class and `id` is an alias for `*mut +objc::runtime::Object` (the pointer to the Objective-C instance). The trait +`IFoo` is needed to allow for the generated inheritance. + +Functions that use or return Objective-C pointers of instance `Foo` will return +`Foo`. The reason this works is because `Foo` represented as `transparent`. +This will be helpful for many Objective-C frameworks. However, there are some +cases where functions return `instancetype` which is a type alias for `id` so +an occasional `foo.0` may be required. An example of this would in the UIKit +framework should you want to add a `UILabel` to a +[UIStackView](https://developer.apple.com/documentation/uikit/uistackview/1616227-addarrangedsubview?language=objc) +you will need to convert the `UILabel` to a `UIView` via `UIView(label.0)`. + +Each class (struct) has an `alloc` and a `dealloc` to match that of some of the alloc +methods found in `NSObject`. + +In order to initialize a class `Foo`, you will have to do something like `let +foo = Foo(Foo::alloc().initWithStuff())`. + +To blocklist an Objective-C method, you should add the bindgen generated method +path (e.g. `IFoo::method` or `IFoo::class_method`) as a blocklist item. + +## Supported Features + +* Inheritance matched to rust traits with prefixes of `I` which +stands for interface. +* Protocols which match to rust traits with prefixes of `P` which +stands for Protocol. +* Classes will generate `struct Foo(id)` where `Foo` is the class +name and `id` is a pointer to the Objective-C Object. +* Blocks + +## Useful Notes + +* If you're targeting `aarch64-apple-ios`, you'll need to have the clang arg +`--target=arm64-apple-ios` as mentioned +[here](https://github.com/rust-lang/rust-bindgen/issues/1211#issuecomment-569804287). +* The generated bindings will almost certainly have some conflicts so you will +have to blocklist a few things. There are a few cases of the parameters being +poorly named in the Objective-C headers. But if you're using anything with +Core Foundation, you'll find that `time.h` as has a variable called timezone that +conflicts with some of the things in `NSCalendar.h`. +* Some small subset of the function headers in the Apple frameworks go against +Apple's guidelines for parameter names and duplicate the names in the header +which won't compile as mentioned +[here](https://github.com/rust-lang/rust-bindgen/issues/1705). +* instancetype return methods does not return `Self` for you given class, it +returns a `mut * objc::runtime::Objc` which is aliased as `id`. This is because +Objective-C's inheritance doesn't perfectly match that of Rust's. +* Depending on what you're trying `bindgen` against, you may end up including +all of Core Foundation and any other frameworks. This will result in a very +long compile time. + +## Not (yet) Supported + +* Nullability attributes which return `Option`s. +* Probably many other things. Feel free to [open an issue](https://github.com/rust-lang/rust-bindgen/issues). + +# Example crate(s) + +* [uikit-sys](https://github.com/simlay/uikit-sys) diff --git a/book/src/opaque.md b/book/src/opaque.md index e1bf600cec..ad15056743 100644 --- a/book/src/opaque.md +++ b/book/src/opaque.md @@ -10,7 +10,7 @@ automatically, but other times it needs some explicit help from you. ### Library -* [`bindgen::Builder::opaque_type`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.opaque_type) +* [`bindgen::Builder::opaque_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.opaque_type) ### Command Line diff --git a/book/src/replacing-types.md b/book/src/replacing-types.md index 7426d2ea55..f47d945deb 100644 --- a/book/src/replacing-types.md +++ b/book/src/replacing-types.md @@ -24,4 +24,4 @@ That way, after code generation, the bindings for the `nsTArray` type are the ones that would be generated for `nsTArray_Simple`. Replacing is only available as an annotation. To replace a C or C++ definition -with a Rust definition, use [blacklisting](./blacklisting.html). +with a Rust definition, use [blocklisting](./blocklisting.md). diff --git a/book/src/requirements.md b/book/src/requirements.md index 14dc192290..cf719a0d61 100644 --- a/book/src/requirements.md +++ b/book/src/requirements.md @@ -7,22 +7,30 @@ This page lists the requirements for running `bindgen` and how to get them. `bindgen` leverages `libclang` to preprocess, parse, and type check C and C++ header files. -It is recommended to use Clang 3.9 or greater, however `bindgen` can run with -older Clangs with some features disabled. +It is required to use Clang 9.0 or greater. -* **If you are generating bindings to C,** 3.7 and 3.8 will probably work OK for -you. - -* **If you are generating bindings to C++,** you almost definitely want 3.9 or -greater. - -### Installing Clang 3.9 +### Installing Clang #### Windows -Download and install the official pre-built binary from +If you use winget: +```powershell +winget install LLVM.LLVM +``` + +Alternatively, you can download and install the official pre-built binary from [LLVM download page](http://releases.llvm.org/download.html). +You will also need to set `LIBCLANG_PATH` as an [environment +variable](https://www.techjunkie.com/environment-variables-windows-10/) pointing +to the `bin` directory of your LLVM install. For example, if you installed LLVM +to `D:\programs\LLVM`, then you'd set the value to be `D:\programs\LLVM\bin`. + +Alternatively, for Mingw64, you can install clang via +```bash +pacman -S mingw64/mingw-w64-x86_64-clang +``` + #### macOS If you use Homebrew: @@ -34,18 +42,16 @@ $ brew install llvm If you use MacPorts: ```bash -$ port install clang-3.9 +$ port install clang ``` #### Debian-based Linuxes ```bash -# apt-get install llvm-3.9-dev libclang-3.9-dev clang-3.9 +# apt install libclang-dev ``` -Ubuntu 16.10 provides the necessary packages directly. If you are using older -version of Ubuntu or other Debian-based distros, you may need to add the LLVM -repos to get version 3.9. See http://apt.llvm.org/. +If you want to use the function `bindgen::Builder::dump_preprocessed_input`, then you also need the package `clang`. #### Arch @@ -53,15 +59,29 @@ repos to get version 3.9. See http://apt.llvm.org/. # pacman -S clang ``` +#### Fedora + +```bash +# dnf install clang-devel +``` + +#### OpenBSD + +```bash +# pkg_add llvm +``` + +Add `export LIBCLANG_PATH=/usr/local/lib` to your profile. + #### From source -If your package manager doesn't yet offer Clang 3.9, you'll need to build from +If your package manager doesn't yet offer Clang 9.0, you'll need to build from source. For that, follow the instructions [here](http://clang.llvm.org/get_started.html). Those instructions list optional steps. For `bindgen`: * Checkout and build clang -* Checkout and build the extra-clang-tools +* Checkout and build `clang-tools-extra` * You do not need to checkout or build compiler-rt * You do not need to checkout or build libcxx diff --git a/book/src/tutorial-1.md b/book/src/tutorial-1.md index 161b1c5546..a26c393b3b 100644 --- a/book/src/tutorial-1.md +++ b/book/src/tutorial-1.md @@ -1,9 +1,20 @@ # Add `bindgen` as a Build Dependency -Declare a build-time dependency on `bindgen` by adding it to the -`[build-dependencies]` section of our crate's `Cargo.toml` metadata file: +First we need to declare a build-time dependency on `bindgen` by adding it to +the `[build-dependencies]` section of our crate's `Cargo.toml` file. + +Please always use the latest version of `bindgen`, as it has the most fixes and +best compatibility. +You can always check the latest version at +[the bindgen page in crates.io](https://crates.io/crates/bindgen). ```toml [build-dependencies] -bindgen = "0.26.3" +bindgen = "0.71.0" ``` + +> ⚠️ **Warning** +> +> `bindgen` needs to be added to the `[build-dependencies]` section, not the normal +> `[dependencies]` section. If you add it as a regular dependency, you will get +> errors like the following: `` error[E0463]: can't find crate for `bindgen` `` diff --git a/book/src/tutorial-2.md b/book/src/tutorial-2.md index e1e88811b0..55cea77799 100644 --- a/book/src/tutorial-2.md +++ b/book/src/tutorial-2.md @@ -14,7 +14,7 @@ Here is our `wrapper.h`: #include ``` -This is also where we would add any [replacement types](./replacing-types.html), +This is also where we would add any [replacement types](./replacing-types.md), if we were using some. [spidermonkey]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/How_to_embed_the_JavaScript_engine diff --git a/book/src/tutorial-3.md b/book/src/tutorial-3.md index b435989ab6..3248f2847f 100644 --- a/book/src/tutorial-3.md +++ b/book/src/tutorial-3.md @@ -1,19 +1,22 @@ # Create a `build.rs` File -We create a `build.rs` file in our crate's root. Cargo will pick up on the existence of this file and compile and executed it before the rest of the crate is built. +We create a `build.rs` file in our crate's root. Cargo will pick up on the existence of this file, then compile and execute it before the rest of the crate is built. This can be used to generate code at compile time. And of course in our case, we will be generating Rust FFI bindings to `bzip2` at compile time. The resulting bindings will be written to `$OUT_DIR/bindings.rs` where `$OUT_DIR` is chosen by `cargo` and is something like `./target/debug/build/bindgen-tutorial-bzip2-sys-afc7747d7eafd720/out/`. -```rust,ignore -extern crate bindgen; +Note that the associated shared object to `bz2` is `libbz2.so`. In general, a `lib.so` should be referenced in the build file by ``. +```rust,ignore use std::env; use std::path::PathBuf; fn main() { + // Tell cargo to look for shared libraries in the specified directory + println!("cargo:rustc-link-search=/path/to/lib"); + // Tell cargo to tell rustc to link the system bzip2 // shared library. println!("cargo:rustc-link-lib=bz2"); @@ -25,6 +28,9 @@ fn main() { // The input header we would like to generate // bindings for. .header("wrapper.h") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. @@ -41,6 +47,6 @@ fn main() { Now, when we run `cargo build`, our bindings to `bzip2` are generated on the fly! -[There's more info about `build.rs` files in the crates.io documentation.][build-rs] +[There's more info about `build.rs` files in the Cargo documentation.][build-rs] -[build-rs]: http://doc.crates.io/build-script.html +[build-rs]: https://doc.rust-lang.org/cargo/reference/build-scripts.html diff --git a/book/src/tutorial-5.md b/book/src/tutorial-5.md index 1690ef532c..8e308f82d6 100644 --- a/book/src/tutorial-5.md +++ b/book/src/tutorial-5.md @@ -1,11 +1,11 @@ -# Write a Sanity Test +# Write a Smoke Test -Finally, to tie everything together, let's write a sanity test that round trips +Finally, to tie everything together, let's write a smoke test that round trips some text through compression and decompression, and then asserts that it came back out the same as it went in. This is a little wordy using the raw FFI bindings, but hopefully we wouldn't usually ask people to do this, we'd provide a nice Rust-y API on top of the raw FFI bindings for them. However, since this -is for testing the bindings directly, our sanity test will use the bindings +is for testing the bindings directly, our smoke test will use the bindings directly. The test data I'm round tripping are some Futurama quotes I got off the internet @@ -40,7 +40,7 @@ mod tests { r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), r if r == (BZ_OK as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } // Compress `input` into `compressed_output`. @@ -55,15 +55,15 @@ mod tests { r if r == (BZ_FINISH_OK as _) => panic!("BZ_FINISH_OK"), r if r == (BZ_SEQUENCE_ERROR as _) => panic!("BZ_SEQUENCE_ERROR"), r if r == (BZ_STREAM_END as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } // Finish the compression stream. let result = BZ2_bzCompressEnd(&mut stream as *mut _); match result { - r if r == (BZ_PARAM_ERROR as _) => panic!(BZ_PARAM_ERROR), + r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), r if r == (BZ_OK as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } // Construct a decompression stream. @@ -76,7 +76,7 @@ mod tests { r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), r if r == (BZ_OK as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } // Decompress `compressed_output` into `decompressed_output`. @@ -92,7 +92,7 @@ mod tests { r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), r if r == (BZ_OK as _) => panic!("BZ_OK"), r if r == (BZ_STREAM_END as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } // Close the decompression stream. @@ -100,7 +100,7 @@ mod tests { match result { r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), r if r == (BZ_OK as _) => {}, - r => panic!("Unknown return value = {}", r), + r => panic!("Unknown return value = {r}"), } assert_eq!(input, &decompressed_output[..]); @@ -109,7 +109,7 @@ mod tests { } ``` -Now let's run `cargo test` again and verify that everying is linking and binding +Now let's run `cargo test` again and verify that everything is linking and binding properly! ```bash diff --git a/book/src/using-bitfields.md b/book/src/using-bitfields.md index c6d2c7e80e..6aaab2203d 100644 --- a/book/src/using-bitfields.md +++ b/book/src/using-bitfields.md @@ -5,12 +5,17 @@ As Rust does not support bitfields, Bindgen generates a struct for each with the following characteristics * Immutable getter functions for each bitfield named `````` * Setter functions for each contiguous block of bitfields named ```set_``` -* Far each contiguous block of bitfields, Bindgen emits an opaque physical field that contains one or more logical bitfields +* For each contiguous block of bitfields, Bindgen emits an opaque physical field that contains one or more logical bitfields * A static constructor ```new_bitfield_{1, 2, ...}``` with a parameter for each bitfield contained within the opaque physical field. +To keep bindgen from generating the bitfield unit struct, it can be blocklisted like any +other type, i.e. `--blocklist-type "__BindgenBitfieldUnit"`. This may be useful if +you want to define a custom implementation, or your generated bindings import a +pre-existing definition for the bitfield unit type. + ## Bitfield examples -For this discussion, we will use the following C type definitions and functions. +For this discussion, we will use the following C type definitions and functions: ```c typedef struct { unsigned int a: 1; @@ -71,7 +76,9 @@ StructWithBitfields: a:1, b:1, c:0 To create a new bitfield in Rust, use the bitfield allocation unit constructor. -Note: This requires the Builder's derive_default to be set to true, otherwise the necessary Default functions won't be generated. +Note: This requires the `Builder`'s [`derive_default`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default) +to be set to `true`. Otherwise the necessary `Default` functions won't be +generated. ```rust,ignore let bfield = StructWithBitfields{ @@ -85,5 +92,5 @@ Note: This requires the Builder's derive_default to be set to true, otherwise th This will print out ```text -StructWithBitfields: a:1, b:0, c:2 +StructWithBitfields: a:0, b:0, c:0 ``` diff --git a/book/src/using-fam.md b/book/src/using-fam.md new file mode 100644 index 0000000000..aaf19c90fd --- /dev/null +++ b/book/src/using-fam.md @@ -0,0 +1,163 @@ +# Using C structures with Flexible Array Members + +Since time immemorial, C programmers have been using what was called "the struct +hack". This is a technique for packing a fixed-size structure and a +variable-sized tail within the same memory allocation. Typically this looks +like: + +```c +struct MyRecord { + time_t timestamp; + unsigned seq; + size_t len; + char payload[0]; +}; +``` + +Because this is so useful, it was standardized in C99 as "flexible array +members", using almost identical syntax: +```c +struct MyRecord { + time_t timestamp; + unsigned seq; + size_t len; + char payload[]; // NOTE: empty [] +}; +``` + +Bindgen supports these structures in two different ways. + +## `__IncompleteArrayField` + +By default, bindgen will generate the corresponding Rust structure: +```rust,ignore +#[repr(C)] +struct MyRecord { + pub timestamp: time_t, + pub seq: ::std::os::raw::c_uint, + pub len: usize, + pub payload: __IncompleteArrayField<::std::os::raw::c_char>, +} +``` + +The `__IncompleteArrayField` type is zero-sized, so this structure represents +the prefix without any trailing data. In order to access that data, it provides +the `as_slice` unsafe method: +```rust,ignore + // SAFETY: there's at least `len` bytes allocated and initialized after `myrecord` + let payload = unsafe { myrecord.payload.as_slice(myrecord.len) }; +``` +There's also `as_mut_slice` which does the obvious. + +These are `unsafe` simply because it's up to you to provide the right length (in +elements of whatever type `payload` is) as there's no way for Rust or Bindgen to +know. In this example, the length is a very straightforward `len` field in the +structure, but it could be encoded in any number of ways within the structure, +or come from somewhere else entirely. + +One big caveat with this technique is that `std::mem::size_of` (or +`size_of_val`) will *only* include the size of the prefix structure. if you're +working out how much storage the whole structure is using, you'll need to add +the suffix yourself. + +## Using Dynamically Sized Types + +If you invoke bindgen with the `--flexarray-dst` option, it will generate +something not quite like this: + +```rust,ignore +#[repr(C)] +struct MyRecord { + pub timestamp: time_t, + pub seq: ::std::os::raw::c_uint, + pub len: usize, + pub payload: [::std::os::raw::c_char], +} +``` +Rust has a set of types which are almost exact analogs for these Flexible Array +Member types: the Dynamically Sized Type ("DST"). + +This looks almost identical to a normal Rust structure, except that you'll note +the type of the `payload` field is a raw slice `[...]` rather than the usual +reference to slice `&[...]`. + +That `payload: [c_char]` is telling Rust that it can't directly know the total +size of this structure - the `payload` field takes an amount of space that's +determined at runtime. This means you can't directly use values of this type, +only references: `&MyRecord`. + +In practice, this is very awkward. So instead, bindgen generates: +```rust,ignore +#[repr(C)] +struct MyRecord { + pub timestamp: time_t, + pub seq: ::std::os::raw::c_uint, + pub len: usize, + pub payload: FAM, +} +``` + +That is: +1. a type parameter `FAM` which represents the type of the `payload` field, +2. it's `?Sized` meaning it can be unsized (ie, a DST) +3. it has the default type of `[c_char; 0]` - that is a zero-sized array of characters + +This means that referencing plain `MyRecord` will be exactly like `MyRecord` +with `__IncompleteArrayField`: it is a fixed-sized structure which you can +manipulate like a normal Rust value. + +But how do you get to the DST part? + +Bindgen will also implement a set of helper methods for this: + +```rust,ignore +// Static sized variant +impl MyRecord<[::std::os::raw::c_char; 0]> { + pub unsafe fn flex_ref(&self, len: usize) -> &MyRecord<[::std::os::raw::c_char]> { ... } + pub unsafe fn flex_mut_ref(&mut self, len: usize) -> &mut MyRecord<[::std::os::raw::c_char]> { ... } + // And some raw pointer variants +} +``` +These will take a sized `MyRecord<[c_char; 0]>` and a length in elements, and +return a reference to a DST `MyRecord<[c_char]>` where the `payload` field is a +fully usable slice of `len` characters. + +The magic here is that the reference is a fat pointer, which not only encodes +the address, but also the dynamic size of the final field, just like a reference +to a slice is. This means that you get full bounds checked access to the +`payload` field like any other Rust slice. + +It also means that doing `mem::size_of_val(myrecord)` will return the *complete* +size of this structure, including the suffix. + +You can go the other way: +```rust,ignore +// Dynamic sized variant +impl MyRecord<[::std::os::raw::c_char]> { + pub fn fixed(&self) -> (&MyRecord<[::std::os::raw::c_char; 0]>, usize) { ... } + pub fn fixed_mut(&mut self) -> (&mut MyRecord<[::std::os::raw::c_char; 0]>, usize) { ... } + pub fn layout(len: usize) -> std::alloc::Layout { ... } +} +``` +which takes the DST variant of the structure and returns the sized variant, +along with the number of elements are after it. These are all completely safe +because all the information needed is part of the fat `&self` reference. + +The `layout` function takes a length and returns the `Layout` - that is, size +and alignment, so that you can allocate memory for the structure (for example, +using `malloc` so you can pass it to a C function). + +Unfortunately the language features needed to support these methods are still unstable: +- [ptr_metadata](https://doc.rust-lang.org/beta/unstable-book/library-features/ptr-metadata.html), + which enables all the fixed<->DST conversions, and +- [layout_for_ptr](https://doc.rust-lang.org/beta/unstable-book/library-features/layout-for-ptr.html), + which allows he `layout` method + +As a result, if you don't specify `--rust-target nightly` you'll just get the +bare type definitions, but no real way to use them. It's often convenient to add +the +```bash +--raw-line '#![feature(ptr_metadata,layout_for_ptr)]' +``` +option if you're generating Rust as a stand-alone crate. Otherwise you'll need +to add the feature line to your containing crate. diff --git a/book/src/using-unions.md b/book/src/using-unions.md index 9a0cc3ee9a..5ae764a33d 100644 --- a/book/src/using-unions.md +++ b/book/src/using-unions.md @@ -35,8 +35,8 @@ typedef union { ### Library -* [`bindgen::Builder::rust_target()`](https://docs.rs/bindgen/0.29.0/bindgen/struct.Builder.html#method.rust_target) -* [`bindgen::Builder::derive_default()`](https://docs.rs/bindgen/0.29.0/bindgen/struct.Builder.html#method.derive_default) +* [`bindgen::Builder::rust_target()`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.rust_target) +* [`bindgen::Builder::derive_default()`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default) ### Command Line @@ -66,11 +66,11 @@ When using the `union` builtin type, there are two choices for initialization: mod bindings_builtin_union; fn union_builtin() { - // Initalize the union to zero + // Initialize the union to zero let x = bindings_builtin_union::greek_t::default(); // If `--with-derive-default` option is not used, the following may be used - // to initalize the union to zero: + // to initialize the union to zero: let x = unsafe { std::mem::zeroed::() }; // Or, it is possible to initialize exactly one variant of the enum: diff --git a/book/src/visibility.md b/book/src/visibility.md new file mode 100644 index 0000000000..ac0aac15da --- /dev/null +++ b/book/src/visibility.md @@ -0,0 +1,37 @@ +# Making fields private + +Fields can be made private for various reasons. You may wish to enforce some invariant on the fields of a structure, which cannot be achieved if the field is public and can be set by any code. For example, you may wish to ensure that a pointer always points to something appropriate. + +### Annotation + +```c +struct OneFieldPrivate { + /** Null-terminated, static string.
*/ + const char *s; + bool b; +}; + +/**
*/ +struct MostFieldsPrivate { + int a; + bool b; + /**
*/ + char c; +}; +``` + +Then in Rust: + +```rust +# #[repr(C)] +# pub struct OneFieldPrivate { +# s: *const ::std::os::raw::c_char, +# pub b: bool, +# } + +impl OneFieldPrivate { + pub fn new(s: &'static std::ffi::CStr, b: bool) -> Self { + OneFieldPrivate { s: s.as_ptr(), b } + } +} +``` diff --git a/book/src/whitelisting.md b/book/src/whitelisting.md deleted file mode 100644 index fdf5c56ba8..0000000000 --- a/book/src/whitelisting.md +++ /dev/null @@ -1,31 +0,0 @@ -# Whitelisting - -Whitelisting allows us to be precise about which type, function, and global -variable definitions `bindgen` generates bindings for. By default, if we don't -specify any whitelisting rules, everything is considered whitelisted. This may -not be desirable because of either - -* the generated bindings contain a lot of extra defintions we don't plan on using, or -* the header file contains C++ features for which Rust does not have a - corresponding form (such as partial template specialization), and we would - like to avoid these definitions - -If we specify whitelisting rules, then `bindgen` will only generate bindings to -types, functions, and global variables that match the whitelisting rules, or are -transitively used by a definition that matches them. - -### Library - -* [`bindgen::Builder::whitelist_type`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.whitelist_type) -* [`bindgen::Builder::whitelist_function`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.whitelist_function) -* [`bindgen::Builder::whitelist_var`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.whitelist_var) - -### Command Line - -* `--whitelist-type ` -* `--whitelist-function ` -* `--whitelist-var ` - -### Annotations - -None. diff --git a/build.rs b/build.rs deleted file mode 100644 index a20c3781cc..0000000000 --- a/build.rs +++ /dev/null @@ -1,73 +0,0 @@ -mod target { - use std::env; - use std::fs::File; - use std::io::Write; - use std::path::{Path, PathBuf}; - - pub fn main() { - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - - let mut dst = File::create(Path::new(&out_dir).join("host-target.txt")) - .unwrap(); - dst.write_all(env::var("TARGET").unwrap().as_bytes()) - .unwrap(); - } -} - -mod testgen { - use std::char; - use std::env; - use std::ffi::OsStr; - use std::fs::{self, File}; - use std::io::Write; - use std::path::{Path, PathBuf}; - - pub fn main() { - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let mut dst = File::create(Path::new(&out_dir).join("tests.rs")) - .unwrap(); - - let manifest_dir = - PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let headers_dir = manifest_dir.join("tests").join("headers"); - - let headers = match fs::read_dir(headers_dir) { - Ok(dir) => dir, - // We may not have headers directory after packaging. - Err(..) => return, - }; - - let entries = - headers.map(|result| result.expect("Couldn't read header file")); - - println!("cargo:rerun-if-changed=tests/headers"); - - for entry in entries { - match entry.path().extension().and_then(OsStr::to_str) { - Some("h") | Some("hpp") => { - let func = entry - .file_name() - .to_str() - .unwrap() - .replace(|c| !char::is_alphanumeric(c), "_") - .replace("__", "_") - .to_lowercase(); - writeln!( - dst, - "test_header!(header_{}, {:?});", - func, - entry.path() - ).unwrap(); - } - _ => {} - } - } - - dst.flush().unwrap(); - } -} - -fn main() { - target::main(); - testgen::main(); -} diff --git a/ci/assert-docs.sh b/ci/assert-docs.sh deleted file mode 100755 index 2bbc35af38..0000000000 --- a/ci/assert-docs.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/.." - -cargo check --features "$BINDGEN_FEATURES testing_only_docs" diff --git a/ci/assert-no-diff.sh b/ci/assert-no-diff.sh deleted file mode 100755 index 14f2aa2161..0000000000 --- a/ci/assert-no-diff.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/.." - -git add -u -git diff @ -git diff-index --quiet HEAD diff --git a/ci/assert-rustfmt.sh b/ci/assert-rustfmt.sh deleted file mode 100755 index bd268600ec..0000000000 --- a/ci/assert-rustfmt.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/.." - -# Ensure we have the most up-to-date `rustfmt`. -cargo install -f rustfmt - -# Run `rustfmt` on the crate! If `rustfmt` can't make a long line shorter, it -# prints an error and exits non-zero, so tell it to kindly shut its yapper and -# make sure it doesn't cause us to exit this whole script non-zero. -cargo fmt --quiet || true - -# Exit non-zero if this resulted in any diffs. -./ci/assert-no-diff.sh - diff --git a/ci/before_install.sh b/ci/before_install.sh deleted file mode 100644 index fcc00ea2cc..0000000000 --- a/ci/before_install.sh +++ /dev/null @@ -1,61 +0,0 @@ -set -ex -pushd ~ - -# Workaround for Travis CI macOS bug (https://github.com/travis-ci/travis-ci/issues/6307) -if [ "${TRAVIS_OS_NAME}" == "osx" ]; then - rvm get head || true -fi - -function llvm_linux_target_triple() { - if [ "$1" == "5.0" ]; then - echo "linux-x86_64-ubuntu14.04" - else - echo "x86_64-linux-gnu-ubuntu-14.04" - fi -} - -function llvm_version_triple() { - if [ "$1" == "3.5" ]; then - echo "3.5.2" - elif [ "$1" == "3.6" ]; then - echo "3.6.2" - elif [ "$1" == "3.7" ]; then - echo "3.7.1" - elif [ "$1" == "3.8" ]; then - echo "3.8.1" - elif [ "$1" == "3.9" ]; then - echo "3.9.0" - elif [ "$1" == "4.0" ]; then - echo "4.0.0" - elif [ "$1" == "5.0" ]; then - echo "5.0.0" - fi -} - -function llvm_download() { - export LLVM_VERSION_TRIPLE=`llvm_version_triple ${LLVM_VERSION}` - export LLVM=clang+llvm-${LLVM_VERSION_TRIPLE}-$1 - export LLVM_DIRECTORY="$HOME/.llvm/${LLVM}" - - if [ -d "${LLVM_DIRECTORY}" ]; then - echo "Using cached LLVM download for ${LLVM}..." - else - wget http://releases.llvm.org/${LLVM_VERSION_TRIPLE}/${LLVM}.tar.xz - mkdir -p "${LLVM_DIRECTORY}" - tar xf ${LLVM}.tar.xz -C "${LLVM_DIRECTORY}" --strip-components=1 - fi - - export LLVM_CONFIG_PATH="${LLVM_DIRECTORY}/bin/llvm-config" -} - -if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - llvm_download `llvm_linux_target_triple ${LLVM_VERSION}` - export LD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$LD_LIBRARY_PATH -else - llvm_download x86_64-apple-darwin - cp "${LLVM_DIRECTORY}/lib/libclang.dylib" /usr/local/lib/libclang.dylib - export DYLD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$DYLD_LIBRARY_PATH -fi - -popd -set +e diff --git a/ci/deploy-book.sh b/ci/deploy-book.sh deleted file mode 100755 index 8ed3ed4690..0000000000 --- a/ci/deploy-book.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/../book" - -# Ensure mdbook is installed. -cargo install mdbook --vers "^0.0.22" || true -export PATH="$PATH:~/.cargo/bin" - -# Get the git revision we are on. -rev=$(git rev-parse --short HEAD) - -# Build the users guide book and go into the built book's directory. -rm -rf ./book -mdbook build -cd ./book - -# Make the built book directory a new git repo, fetch upstream, make a new -# commit on gh-pages, and push it upstream. - -git init -git config user.name "Travis CI" -git config user.email "builds@travis-ci.org" - -git remote add upstream "https://$GH_TOKEN@github.com/rust-lang-nursery/rust-bindgen.git" -git fetch upstream -git reset upstream/gh-pages - -touch . - -git add -A . -git commit -m "Rebuild users guide at ${rev}" -git push upstream HEAD:gh-pages diff --git a/ci/no-includes.sh b/ci/no-includes.sh index 6aa0fc125e..32c20059e0 100755 --- a/ci/no-includes.sh +++ b/ci/no-includes.sh @@ -1,13 +1,17 @@ #!/usr/bin/env bash # Don't allow any system include directives in tests. +# +# We make an exception for stdarg.h which is used for +# the wrapped va_list feature. stdarg.h is available since C89 +# therefor not having this header is a sign of a bigger issue. set -eu cd "$(dirname "$0")/.." echo "Checking for #include directives of system headers..." -grep -rn '#include\s*<.*>' tests/headers || { +grep -rn '#include\s*<(?!stdarg).*>' bindgen-tests/tests/headers || { echo "Found none; OK!" exit 0 } diff --git a/ci/script.sh b/ci/script.sh deleted file mode 100755 index 91ea7c1368..0000000000 --- a/ci/script.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/.." - -# Note that `$BINDGEN_PROFILE` is never in quotes so that it expands to nothing -# (not even an empty string argument) when the variable is empty. This is -# necessary so we don't pass an unexpected flag to cargo. - -export RUST_BACKTRACE=1 - -case "$BINDGEN_JOB" in - "test") - # Need rustfmt to compare the test expectations. - rustup update nightly - rustup run nightly cargo install -f rustfmt-nightly - - cargo test $BINDGEN_PROFILE --features "$BINDGEN_FEATURES" - ./ci/assert-no-diff.sh - ;; - - "integration") - cd ./bindgen-integration - cargo test $BINDGEN_PROFILE --features "$BINDGEN_FEATURES" - ;; - - "expectations") - cd ./tests/expectations - cargo test $BINDGEN_PROFILE - ;; - - "misc") - ./ci/assert-docs.sh - ./ci/test-book.sh - ./ci/no-includes.sh - # `rustfmt` isn't reaching a fixed point on bindgen - # code... https://github.com/rust-lang-nursery/rustfmt/issues/1376 - # ./ci/assert-rustfmt.sh - ;; - - "quickchecking") - cd ./tests/quickchecking - # TODO: Actually run quickchecks once `bindgen` is reliable enough. - cargo test - ;; - *) - echo "Error! Unknown \$BINDGEN_JOB: '$BINDGEN_JOB'" - exit 1 -esac diff --git a/ci/test-book.sh b/ci/test-book.sh deleted file mode 100755 index b2007e7c59..0000000000 --- a/ci/test-book.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -xeu -cd "$(dirname "$0")/../book" - -cargo install mdbook --vers "^0.0.22" || true -export PATH="$PATH:~/.cargo/bin" - -mdbook build -mdbook test diff --git a/ci/test.bat b/ci/test.bat index 507537c08e..d4a1c4a08a 100644 --- a/ci/test.bat +++ b/ci/test.bat @@ -29,10 +29,10 @@ findstr /r /c:"#include *<.*>" tests\headers\* >nul 2>&1 && ( cargo test --features "%BINDGEN_FEATURES%" || exit /b 1 call .\ci\assert-no-diff.bat -cargo test --features "%BINDGEN_FEATURES% testing_only_extra_assertions" || exit /b 1 +cargo test --features "%BINDGEN_FEATURES% __testing_only_extra_assertions" || exit /b 1 call .\ci\assert-no-diff.bat -cargo test --release --features "%BINDGEN_FEATURES% testing_only_extra_assertions" || exit /b 1 +cargo test --release --features "%BINDGEN_FEATURES% __testing_only_extra_assertions" || exit /b 1 call .\ci\assert-no-diff.bat ::Now test the expectations' size and alignment tests. diff --git a/ci/test.sh b/ci/test.sh new file mode 100755 index 0000000000..587263804b --- /dev/null +++ b/ci/test.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +# Bail on first error +set -e +# Bail if an unset variable is encountered +set -u +# Enable debugging output +set -x +# Give a pipeline a non-zero exit code if one of its constituents fails +set -o pipefail + +set_llvm_env() { + export LLVM_CONFIG_PATH=${LLVM_PATH}/bin/llvm-config + echo "LLVM_CONFIG_PATH=$LLVM_CONFIG_PATH" + + export LIBCLANG_PATH=${LLVM_PATH}/lib/ + echo "LIBCLANG_PATH=$LIBCLANG_PATH" + + export CLANG_PATH=${LLVM_PATH}/bin/clang + echo "CLANG_PATH=$CLANG_PATH" +} + +assert_no_diff() { + git add -u + git diff @ + git diff-index --quiet HEAD +} + +get_cargo_args() { + local args="" + if [ "$BINDGEN_RELEASE_BUILD" == "1" ]; then + args+=" --release" + fi + if [ "$BINDGEN_NO_DEFAULT_FEATURES" == "1" ]; then + args+=" --no-default-features" + fi + local features="" + if [ "$BINDGEN_FEATURE_RUNTIME" == "1" ]; then + features+="runtime" + fi + if [ "$BINDGEN_FEATURE_EXTRA_ASSERTS" == "1" ]; then + features+=" __testing_only_extra_assertions" + fi + if [ ! -z "$features" ]; then + args+=" --features $(echo $features | tr ' ' ',')" + fi + echo $args +} + +set_llvm_env + +CARGO_ARGS=`get_cargo_args` + +# Ensure we build without warnings +RUSTFLAGS="-Dwarnings" cargo check $CARGO_ARGS + +# Run the tests +(cd bindgen-tests && cargo test $CARGO_ARGS) + +assert_no_diff + +# Run the integration tests +(cd bindgen-integration && cargo test $CARGO_ARGS) + +if [ "$BINDGEN_RUST_FOR_LINUX_TEST" == "1" ]; then + # Run the Rust for Linux test + # + # This is intended to be an end-to-end test that runs what Linux kernel + # developers/users would do. It is a quick, build-only test of the Rust code + # in the Linux kernel. + + # Put LLVM binaries in the path for `LLVM=1`. The LLVM `bin` directory should + # go first since there are others in the Ubuntu image. + export PATH="${LLVM_PATH}/bin:${PATH}" + + # Kernel build dependency: `bindgen-cli`, which is under test. + # + # Using `cargo build` (and adding the two common profiles to the `$PATH`) so + # that we can use `$CARGO_ARGS` as is, since `cargo install` does not support + # `--release`. `--target-dir` is used to isolate from other possible tests. + # A cleaner alternative is using `--out-dir`, but it is unstable. + (cd bindgen-cli && cargo build --target-dir ${HOME}/.bindgen $CARGO_ARGS) + export PATH="${HOME}/.bindgen/release:${HOME}/.bindgen/debug:${PATH}" + + # Kernel build dependency: `libelf-dev`. + sudo apt-get update + sudo apt-get install libelf-dev + + # Kernel build dependency: the Rust standard library sources. + # + # `rustup` is used here to install the `rust-src` component (instead of using + # `actions-rs/toolchain`'s `components` option in the workflow step) since we + # only need it for this test, and anyway the action installs `rustup`. + rustup component add rust-src + + # Ideally this should be updated from time to time (e.g. every kernel `-rc1`), + # and each update should only contain this change. + # + # Both commit hashes and tags are supported. + LINUX_VERSION=v6.17-rc2 + + # Download Linux at a specific commit + mkdir -p linux + git -C linux init + git -C linux remote add origin https://github.com/torvalds/linux.git + git -C linux fetch --depth 1 origin ${LINUX_VERSION} + git -C linux checkout FETCH_HEAD + + # Configure Rust for Linux + cat < linux/kernel/configs/rfl-for-bindgen-ci.config +# CONFIG_WERROR is not set + +CONFIG_RUST=y + +CONFIG_SAMPLES=y +CONFIG_SAMPLES_RUST=y + +CONFIG_SAMPLE_RUST_MINIMAL=m +CONFIG_SAMPLE_RUST_PRINT=y + +CONFIG_RUST_PHYLIB_ABSTRACTIONS=y +CONFIG_AX88796B_PHY=y +CONFIG_AX88796B_RUST_PHY=y + +CONFIG_KUNIT=y +CONFIG_RUST_KERNEL_DOCTESTS=y +EOF + + make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + rustavailable \ + defconfig \ + rfl-for-bindgen-ci.config + + # Build Rust for Linux + make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + samples/rust/rust_minimal.o \ + samples/rust/rust_print_main.o \ + drivers/net/phy/ax88796b_rust.o +fi diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000..ec210a9878 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +missing-docs-in-crate-items = true diff --git a/csmith-fuzzing/README.md b/csmith-fuzzing/README.md index c7e8eaf9d7..cdd6d0866a 100644 --- a/csmith-fuzzing/README.md +++ b/csmith-fuzzing/README.md @@ -62,4 +62,4 @@ related to fuzzing with `csmith`, by looking up [csmith]: https://github.com/csmith-project/csmith [creducing]: ../CONTRIBUTING.md#using-creduce-to-minimize-test-cases -[csmith-issues]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=label%3AA-csmith +[csmith-issues]: https://github.com/rust-lang/rust-bindgen/issues?q=label%3AA-csmith diff --git a/csmith-fuzzing/driver.py b/csmith-fuzzing/driver.py index 8bf76e0b4d..1d3af540fd 100755 --- a/csmith-fuzzing/driver.py +++ b/csmith-fuzzing/driver.py @@ -232,9 +232,9 @@ def print_issue_template(args, failing_test_case, predicate_command, result): print(""" -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! -! File this issue at https://github.com/rust-lang-nursery/rust-bindgen/issues/new ! -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +! File this issue at https://github.com/rust-lang/rust-bindgen/issues/new ! +! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! --------------- 8< --------------- 8< --------------- 8< --------------- diff --git a/csmith-fuzzing/predicate.py b/csmith-fuzzing/predicate.py index 3bf452ef19..6ca5047659 100755 --- a/csmith-fuzzing/predicate.py +++ b/csmith-fuzzing/predicate.py @@ -65,6 +65,10 @@ reducing = parser.add_argument_group("reducing arguments", REDUCING_DESC.strip()) +reducing.add_argument( + "--release", + action="store_true", + help="Use a release instead of a debug build.") reducing.add_argument( "--expect-bindgen-fail", action="store_true", @@ -76,6 +80,7 @@ reducing.add_argument( "--bindings-grep", type=str, + nargs='*', help="Exit non-zero if the given regexp pattern is not found in the emitted bindings.") reducing.add_argument( @@ -83,6 +88,10 @@ action="store_false", dest="rustc", help="Do not attempt to compile the emitted bindings with `rustc`.") +reducing.add_argument( + "--extra-compile-file", + type=str, + help="Append the content of this extra file to the end of the emitted bindings just before compiling it.") reducing.add_argument( "--expect-compile-fail", action="store_true", @@ -190,13 +199,13 @@ def run_bindgen(args, bindings): manifest_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..", "Cargo.toml")) - child = run( - ["cargo", "run", - "--manifest-path", manifest_path, - "--", - args.input, "-o", bindings] + shlex.split(args.bindgen_args), - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) + command = ["cargo", "run", "--manifest-path", manifest_path] + if args.release: + command += ["--release"] + command += ["--", args.input, "-o", bindings] + command += shlex.split(args.bindgen_args) + + child = run(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) if args.bindgen_grep: pattern = regexp(args.bindgen_grep) @@ -210,17 +219,21 @@ def run_bindgen(args, bindings): if not args.expect_bindgen_fail and child.returncode != 0: exit_1("Error: running `bindgen` failed", child) - if args.bindings_grep: - pattern = regexp(args.bindings_grep) + for arg in args.bindings_grep or []: + pattern = regexp(arg) with open(bindings, mode="r") as f: if not contains(pattern, f): - print("Error: expected the emitted bindings to contain '{}', but they didn't".format(args.bindings_grep)) + print("Error: expected the emitted bindings to contain '{}', but they didn't".format(arg)) print("---------- {} ----------------------------------------------".format(bindings)) f.seek(0) print(f.read()) raise ExitOne() def run_rustc(args, bindings, test_exe): + if args.extra_compile_file: + with open(bindings, mode="a") as outfile: + with open(args.extra_compile_file, mode="r") as infile: + outfile.write(infile.read()) child = run( ["rustc", "--crate-type", "lib", "--test", "-o", test_exe, bindings], stdout=subprocess.PIPE, diff --git a/dist-workspace.toml b/dist-workspace.toml new file mode 100644 index 0000000000..9da713f523 --- /dev/null +++ b/dist-workspace.toml @@ -0,0 +1,28 @@ +[workspace] +members = ["cargo:."] + +# Config for 'dist' +[dist] +# The preferred dist version to use in CI (Cargo.toml SemVer syntax) +cargo-dist-version = "0.28.0" +# CI backends to support +ci = "github" +# The installers to generate for each app +installers = ["shell"] +# Target platforms to build apps for (Rust target-triple syntax) +targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-pc-windows-msvc", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"] +# Whether to consider the binaries in a package for distribution (defaults true) +dist = false +# Which actions to run on pull requests +pr-run-mode = "plan" +# Whether to install an updater program +install-updater = false +# Path that installers should place binaries in +install-path = "CARGO_HOME" + +[dist.github-custom-runners] +global = "ubuntu-22.04" +aarch64-apple-darwin = "macos-14" +x86_64-apple-darwin = "macos-13" +x86_64-unknown-linux-gnu = "ubuntu-22.04" +aarch64-unknown-linux-gnu = "ubuntu-24.04-arm" diff --git a/releases/release-announcement-template.md b/releases/release-announcement-template.md index a3887ad713..c33ef85f4c 100644 --- a/releases/release-announcement-template.md +++ b/releases/release-announcement-template.md @@ -37,13 +37,13 @@ Want to help improve our documentation? Found a bug with `bindgen`? [File an issue here.][file-issue] -[GitHub]: https://github.com/rust-lang-nursery/rust-bindgen +[GitHub]: https://github.com/rust-lang/rust-bindgen [crates.io]: https://crates.io/crates/bindgen -[guide]: https://rust-lang-nursery.github.io/rust-bindgen +[guide]: https://rust-lang.github.io/rust-bindgen [docs]: https://docs.rs/bindgen -[contributing]: https://github.com/rust-lang-nursery/rust-bindgen/blob/master/CONTRIBUTING.md -[easy]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy -[less-easy]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy -[looking]: https://github.com/rust-lang-nursery/rust-bindgen/issues/747 -[docs-issues]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AI-needs-docs -[file-issue]: https://github.com/rust-lang-nursery/rust-bindgen/issues/new +[contributing]: https://github.com/rust-lang/rust-bindgen/blob/main/CONTRIBUTING.md +[easy]: https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy +[less-easy]: https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy +[looking]: https://github.com/rust-lang/rust-bindgen/issues/747 +[docs-issues]: https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AI-needs-docs +[file-issue]: https://github.com/rust-lang/rust-bindgen/issues/new diff --git a/rustfmt.toml b/rustfmt.toml index 0a24dd73f6..092e69c1d5 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,2 @@ max_width = 80 -fn_brace_style = "SameLineWhere" -item_brace_style = "SameLineWhere" -struct_lit_multiline_style = "ForceMulti" -where_trailing_comma = true -normalize_comments = false +binop_separator = "back" diff --git a/src/callbacks.rs b/src/callbacks.rs deleted file mode 100644 index f6935a554b..0000000000 --- a/src/callbacks.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! A public API for more fine-grained customization of bindgen behavior. - -pub use ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue}; -pub use ir::int::IntKind; -use std::fmt; -use std::panic::UnwindSafe; - -/// An enum to allow ignoring parsing of macros. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum MacroParsingBehavior { - /// Ignore the macro, generating no code for it, or anything that depends on - /// it. - Ignore, - /// The default behavior bindgen would have otherwise. - Default, -} - -impl Default for MacroParsingBehavior { - fn default() -> Self { - MacroParsingBehavior::Default - } -} - -/// A trait to allow configuring different kinds of types in different -/// situations. -pub trait ParseCallbacks: fmt::Debug + UnwindSafe { - /// This function will be run on every macro that is identified. - fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior { - MacroParsingBehavior::Default - } - - /// The integer kind an integer macro should have, given a name and the - /// value of that macro, or `None` if you want the default to be chosen. - fn int_macro(&self, _name: &str, _value: i64) -> Option { - None - } - - /// This function should return whether, given the a given enum variant - /// name, and value, this enum variant will forcibly be a constant. - fn enum_variant_behavior( - &self, - _enum_name: Option<&str>, - _original_variant_name: &str, - _variant_value: EnumVariantValue, - ) -> Option { - None - } - - /// Allows to rename an enum variant, replacing `_original_variant_name`. - fn enum_variant_name( - &self, - _enum_name: Option<&str>, - _original_variant_name: &str, - _variant_value: EnumVariantValue, - ) -> Option { - None - } -} diff --git a/src/clang.rs b/src/clang.rs deleted file mode 100644 index 04d5c9d300..0000000000 --- a/src/clang.rs +++ /dev/null @@ -1,1846 +0,0 @@ -//! A higher level Clang API built on top of the generated bindings in the -//! `clang_sys` module. - -#![allow(non_upper_case_globals, dead_code)] - - -use cexpr; -use clang_sys::*; -use regex; -use std::{mem, ptr, slice}; -use std::ffi::{CStr, CString}; -use std::fmt; -use std::hash::Hash; -use std::hash::Hasher; -use std::os::raw::{c_char, c_int, c_uint, c_ulong}; - -/// A cursor into the Clang AST, pointing to an AST node. -/// -/// We call the AST node pointed to by the cursor the cursor's "referent". -#[derive(Copy, Clone)] -pub struct Cursor { - x: CXCursor, -} - -impl fmt::Debug for Cursor { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!( - fmt, - "Cursor({} kind: {}, loc: {}, usr: {:?})", - self.spelling(), - kind_to_str(self.kind()), - self.location(), - self.usr() - ) - } -} - -impl Cursor { - /// Get the Unified Symbol Resolution for this cursor's referent, if - /// available. - /// - /// The USR can be used to compare entities across translation units. - pub fn usr(&self) -> Option { - let s = unsafe { cxstring_into_string(clang_getCursorUSR(self.x)) }; - if s.is_empty() { None } else { Some(s) } - } - - /// Is this cursor's referent a declaration? - pub fn is_declaration(&self) -> bool { - unsafe { clang_isDeclaration(self.kind()) != 0 } - } - - /// Get the null cursor, which has no referent. - pub fn null() -> Self { - Cursor { - x: unsafe { clang_getNullCursor() }, - } - } - - /// Get this cursor's referent's spelling. - pub fn spelling(&self) -> String { - unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) } - } - - /// Get this cursor's referent's display name. - /// - /// This is not necessarily a valid identifier. It includes extra - /// information, such as parameters for a function, etc. - pub fn display_name(&self) -> String { - unsafe { cxstring_into_string(clang_getCursorDisplayName(self.x)) } - } - - /// Get the mangled name of this cursor's referent. - pub fn mangling(&self) -> String { - if clang_Cursor_getMangling::is_loaded() { - unsafe { cxstring_into_string(clang_Cursor_getMangling(self.x)) } - } else { - self.spelling() - } - } - - /// Gets the C++ manglings for this cursor, or an error if the function is - /// not loaded or the manglings are not available. - pub fn cxx_manglings(&self) -> Result, ()> { - use clang_sys::*; - if !clang_Cursor_getCXXManglings::is_loaded() { - return Err(()); - } - unsafe { - let manglings = clang_Cursor_getCXXManglings(self.x); - if manglings.is_null() { - return Err(()); - } - let count = (*manglings).Count as usize; - - let mut result = Vec::with_capacity(count); - for i in 0..count { - let string_ptr = (*manglings).Strings.offset(i as isize); - result.push(cxstring_to_string_leaky(*string_ptr)); - } - clang_disposeStringSet(manglings); - Ok(result) - } - } - - /// Returns whether the cursor refers to a built-in definition. - pub fn is_builtin(&self) -> bool { - let (file, _, _, _) = self.location().location(); - file.name().is_none() - } - - /// Get the `Cursor` for this cursor's referent's lexical parent. - /// - /// The lexical parent is the parent of the definition. The semantic parent - /// is the parent of the declaration. Generally, the lexical parent doesn't - /// have any effect on semantics, while the semantic parent does. - /// - /// In the following snippet, the `Foo` class would be the semantic parent - /// of the out-of-line `method` definition, while the lexical parent is the - /// translation unit. - /// - /// ```c++ - /// class Foo { - /// void method(); - /// }; - /// - /// void Foo::method() { /* ... */ } - /// ``` - pub fn lexical_parent(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getCursorLexicalParent(self.x), - } - } - } - - /// Get the referent's semantic parent, if one is available. - /// - /// See documentation for `lexical_parent` for details on semantic vs - /// lexical parents. - pub fn fallible_semantic_parent(&self) -> Option { - let sp = unsafe { - Cursor { - x: clang_getCursorSemanticParent(self.x), - } - }; - if sp == *self || !sp.is_valid() { - return None; - } - Some(sp) - } - - /// Get the referent's semantic parent. - /// - /// See documentation for `lexical_parent` for details on semantic vs - /// lexical parents. - pub fn semantic_parent(&self) -> Cursor { - self.fallible_semantic_parent().unwrap() - } - - /// Return the number of template arguments used by this cursor's referent, - /// if the referent is either a template instantiation. Returns `None` - /// otherwise. - /// - /// NOTE: This may not return `Some` for partial template specializations, - /// see #193 and #194. - pub fn num_template_args(&self) -> Option { - // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while - // `clang_Cursor_getNumTemplateArguments` is totally unreliable. - // Therefore, try former first, and only fallback to the latter if we - // have to. - self.cur_type() - .num_template_args() - .or_else(|| { - let n: c_int = - unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - }) - .or_else(|| { - let canonical = self.canonical(); - if canonical != *self { - canonical.num_template_args() - } else { - None - } - }) - } - - /// Get a cursor pointing to this referent's containing translation unit. - /// - /// Note that we shouldn't create a `TranslationUnit` struct here, because - /// bindgen assumes there will only be one of them alive at a time, and - /// disposes it on drop. That can change if this would be required, but I - /// think we can survive fine without it. - pub fn translation_unit(&self) -> Cursor { - assert!(self.is_valid()); - unsafe { - let tu = clang_Cursor_getTranslationUnit(self.x); - let cursor = Cursor { - x: clang_getTranslationUnitCursor(tu), - }; - assert!(cursor.is_valid()); - cursor - } - } - - /// Is the referent a top level construct? - pub fn is_toplevel(&self) -> bool { - let mut semantic_parent = self.fallible_semantic_parent(); - - while semantic_parent.is_some() && - (semantic_parent.unwrap().kind() == CXCursor_Namespace || - semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias || - semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) - { - semantic_parent = - semantic_parent.unwrap().fallible_semantic_parent(); - } - - let tu = self.translation_unit(); - // Yes, this can happen with, e.g., macro definitions. - semantic_parent == tu.fallible_semantic_parent() - } - - /// There are a few kinds of types that we need to treat specially, mainly - /// not tracking the type declaration but the location of the cursor, given - /// clang doesn't expose a proper declaration for these types. - pub fn is_template_like(&self) -> bool { - match self.kind() { - CXCursor_ClassTemplate | - CXCursor_ClassTemplatePartialSpecialization | - CXCursor_TypeAliasTemplateDecl => true, - _ => false, - } - } - - /// Get the kind of referent this cursor is pointing to. - pub fn kind(&self) -> CXCursorKind { - self.x.kind - } - - /// Returns true is the cursor is a definition - pub fn is_definition(&self) -> bool { - unsafe { clang_isCursorDefinition(self.x) != 0 } - } - - /// Is the referent a template specialization? - pub fn is_template_specialization(&self) -> bool { - self.specialized().is_some() - } - - /// Is the referent a fully specialized template specialization without any - /// remaining free template arguments? - pub fn is_fully_specialized_template(&self) -> bool { - self.is_template_specialization() && - self.kind() != CXCursor_ClassTemplatePartialSpecialization && - self.num_template_args().unwrap_or(0) > 0 - } - - /// Is the referent a template specialization that still has remaining free - /// template arguments? - pub fn is_in_non_fully_specialized_template(&self) -> bool { - if self.is_toplevel() { - return false; - } - - let parent = self.semantic_parent(); - if parent.is_fully_specialized_template() { - return false; - } - - if !parent.is_template_like() { - return parent.is_in_non_fully_specialized_template(); - } - - return true; - } - - /// Is this cursor pointing a valid referent? - pub fn is_valid(&self) -> bool { - unsafe { clang_isInvalid(self.kind()) == 0 } - } - - /// Get the source location for the referent. - pub fn location(&self) -> SourceLocation { - unsafe { - SourceLocation { - x: clang_getCursorLocation(self.x), - } - } - } - - /// Get the source location range for the referent. - pub fn extent(&self) -> CXSourceRange { - unsafe { clang_getCursorExtent(self.x) } - } - - /// Get the raw declaration comment for this referent, if one exists. - pub fn raw_comment(&self) -> Option { - let s = unsafe { - cxstring_into_string(clang_Cursor_getRawCommentText(self.x)) - }; - if s.is_empty() { None } else { Some(s) } - } - - /// Get the referent's parsed comment. - pub fn comment(&self) -> Comment { - unsafe { - Comment { - x: clang_Cursor_getParsedComment(self.x), - } - } - } - - /// Get the referent's type. - pub fn cur_type(&self) -> Type { - unsafe { - Type { - x: clang_getCursorType(self.x), - } - } - } - - /// Given that this cursor's referent is a reference to another type, or is - /// a declaration, get the cursor pointing to the referenced type or type of - /// the declared thing. - pub fn definition(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getCursorDefinition(self.x), - }; - - if ret.is_valid() && ret.kind() != CXCursor_NoDeclFound { - Some(ret) - } else { - None - } - } - } - - /// Given that this cursor's referent is reference type, get the cursor - /// pointing to the referenced type. - pub fn referenced(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getCursorReferenced(self.x), - }; - - if ret.is_valid() { Some(ret) } else { None } - } - } - - /// Get the canonical cursor for this referent. - /// - /// Many types can be declared multiple times before finally being properly - /// defined. This method allows us to get the canonical cursor for the - /// referent type. - pub fn canonical(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getCanonicalCursor(self.x), - } - } - } - - /// Given that this cursor points to either a template specialization or a - /// template instantiation, get a cursor pointing to the template definition - /// that is being specialized. - pub fn specialized(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getSpecializedCursorTemplate(self.x), - }; - if ret.is_valid() { Some(ret) } else { None } - } - } - - /// Assuming that this cursor's referent is a template declaration, get the - /// kind of cursor that would be generated for its specializations. - pub fn template_kind(&self) -> CXCursorKind { - unsafe { clang_getTemplateCursorKind(self.x) } - } - - /// Traverse this cursor's referent and its children. - /// - /// Call the given function on each AST node traversed. - pub fn visit(&self, mut visitor: Visitor) - where - Visitor: FnMut(Cursor) -> CXChildVisitResult, - { - unsafe { - clang_visitChildren( - self.x, - visit_children::, - mem::transmute(&mut visitor), - ); - } - } - - /// Collect all of this cursor's children into a vec and return them. - pub fn collect_children(&self) -> Vec { - let mut children = vec![]; - self.visit(|c| { - children.push(c); - CXChildVisit_Continue - }); - children - } - - /// Does this cursor have any children? - pub fn has_children(&self) -> bool { - let mut has_children = false; - self.visit(|_| { - has_children = true; - CXChildVisit_Break - }); - has_children - } - - /// Does this cursor have at least `n` children? - pub fn has_at_least_num_children(&self, n: usize) -> bool { - assert!(n > 0); - let mut num_left = n; - self.visit(|_| { - num_left -= 1; - if num_left == 0 { - CXChildVisit_Break - } else { - CXChildVisit_Continue - } - }); - num_left == 0 - } - - /// Returns whether the given location contains a cursor with the given - /// kind in the first level of nesting underneath (doesn't look - /// recursively). - pub fn contains_cursor(&self, kind: CXCursorKind) -> bool { - let mut found = false; - - self.visit(|c| if c.kind() == kind { - found = true; - CXChildVisit_Break - } else { - CXChildVisit_Continue - }); - - found - } - - /// Is the referent an inlined function? - pub fn is_inlined_function(&self) -> bool { - clang_Cursor_isFunctionInlined::is_loaded() && - unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 } - } - - /// Get the width of this cursor's referent bit field, or `None` if the - /// referent is not a bit field. - pub fn bit_width(&self) -> Option { - unsafe { - let w = clang_getFieldDeclBitWidth(self.x); - if w == -1 { None } else { Some(w as u32) } - } - } - - /// Get the integer representation type used to hold this cursor's referent - /// enum type. - pub fn enum_type(&self) -> Option { - unsafe { - let t = Type { - x: clang_getEnumDeclIntegerType(self.x), - }; - if t.is_valid() { Some(t) } else { None } - } - } - - /// Get the signed constant value for this cursor's enum variant referent. - /// - /// Returns None if the cursor's referent is not an enum variant. - pub fn enum_val_signed(&self) -> Option { - unsafe { - if self.kind() == CXCursor_EnumConstantDecl { - Some(clang_getEnumConstantDeclValue(self.x) as i64) - } else { - None - } - } - } - - /// Get the unsigned constant value for this cursor's enum variant referent. - /// - /// Returns None if the cursor's referent is not an enum variant. - pub fn enum_val_unsigned(&self) -> Option { - unsafe { - if self.kind() == CXCursor_EnumConstantDecl { - Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64) - } else { - None - } - } - } - - /// Given that this cursor's referent is a `typedef`, get the `Type` that is - /// being aliased. - pub fn typedef_type(&self) -> Option { - let inner = Type { - x: unsafe { clang_getTypedefDeclUnderlyingType(self.x) }, - }; - - if inner.is_valid() { Some(inner) } else { None } - } - - /// Get the linkage kind for this cursor's referent. - /// - /// This only applies to functions and variables. - pub fn linkage(&self) -> CXLinkageKind { - unsafe { clang_getCursorLinkage(self.x) } - } - - /// Get the visibility of this cursor's referent. - pub fn visibility(&self) -> CXVisibilityKind { - if clang_getCursorVisibility::is_loaded() { - unsafe { clang_getCursorVisibility(self.x) } - } else { - CXVisibility_Default - } - } - - /// Given that this cursor's referent is a function, return cursors to its - /// parameters. - pub fn args(&self) -> Option> { - // XXX: We might want to use and keep num_args - // match self.kind() { - // CXCursor_FunctionDecl | - // CXCursor_CXXMethod => { - unsafe { - let w = clang_Cursor_getNumArguments(self.x); - if w == -1 { - None - } else { - let num = w as u32; - - let mut args = vec![]; - for i in 0..num { - args.push(Cursor { - x: clang_Cursor_getArgument(self.x, i as c_uint), - }); - } - Some(args) - } - } - } - - /// Given that this cursor's referent is a function/method call or - /// declaration, return the number of arguments it takes. - /// - /// Returns -1 if the cursor's referent is not a function/method call or - /// declaration. - pub fn num_args(&self) -> Result { - unsafe { - let w = clang_Cursor_getNumArguments(self.x); - if w == -1 { Err(()) } else { Ok(w as u32) } - } - } - - /// Get the access specifier for this cursor's referent. - pub fn access_specifier(&self) -> CX_CXXAccessSpecifier { - unsafe { clang_getCXXAccessSpecifier(self.x) } - } - - /// Is this cursor's referent a field declaration that is marked as - /// `mutable`? - pub fn is_mutable_field(&self) -> bool { - clang_CXXField_isMutable::is_loaded() && - unsafe { clang_CXXField_isMutable(self.x) != 0 } - } - - /// Get the offset of the field represented by the Cursor. - pub fn offset_of_field(&self) -> Result { - if !clang_Cursor_getOffsetOfField::is_loaded() { - return Err(LayoutError::from(-1)); - } - - let offset = unsafe { clang_Cursor_getOffsetOfField(self.x) }; - - if offset < 0 { - Err(LayoutError::from(offset as i32)) - } else { - Ok(offset as usize) - } - } - - /// Is this cursor's referent a member function that is declared `static`? - pub fn method_is_static(&self) -> bool { - unsafe { clang_CXXMethod_isStatic(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is declared `const`? - pub fn method_is_const(&self) -> bool { - unsafe { clang_CXXMethod_isConst(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is virtual? - pub fn method_is_virtual(&self) -> bool { - unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is pure virtual? - pub fn method_is_pure_virtual(&self) -> bool { - unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 } - } - - /// Is this cursor's referent a struct or class with virtual members? - pub fn is_virtual_base(&self) -> bool { - unsafe { clang_isVirtualBase(self.x) != 0 } - } - - /// Try to evaluate this cursor. - pub fn evaluate(&self) -> Option { - EvalResult::new(*self) - } - - /// Return the result type for this cursor - pub fn ret_type(&self) -> Option { - let rt = Type { - x: unsafe { clang_getCursorResultType(self.x) }, - }; - if rt.is_valid() { Some(rt) } else { None } - } - - /// Gets the tokens that correspond to that cursor. - pub fn tokens(&self) -> Option> { - let range = self.extent(); - let mut tokens = vec![]; - unsafe { - let tu = clang_Cursor_getTranslationUnit(self.x); - let mut token_ptr = ptr::null_mut(); - let mut num_tokens: c_uint = 0; - clang_tokenize(tu, range, &mut token_ptr, &mut num_tokens); - if token_ptr.is_null() { - return None; - } - - let token_array = - slice::from_raw_parts(token_ptr, num_tokens as usize); - for &token in token_array.iter() { - let kind = clang_getTokenKind(token); - let spelling = - cxstring_into_string(clang_getTokenSpelling(tu, token)); - - tokens.push(Token { - kind: kind, - spelling: spelling, - }); - } - clang_disposeTokens(tu, token_ptr, num_tokens); - } - Some(tokens) - } - - /// Gets the tokens that correspond to that cursor as `cexpr` tokens. - pub fn cexpr_tokens(self) -> Option> { - use cexpr::token; - - self.tokens().map(|tokens| { - tokens - .into_iter() - .filter_map(|token| { - let kind = match token.kind { - CXToken_Punctuation => token::Kind::Punctuation, - CXToken_Literal => token::Kind::Literal, - CXToken_Identifier => token::Kind::Identifier, - CXToken_Keyword => token::Kind::Keyword, - // NB: cexpr is not too happy about comments inside - // expressions, so we strip them down here. - CXToken_Comment => return None, - _ => { - error!("Found unexpected token kind: {:?}", token); - return None; - } - }; - - Some(token::Token { - kind: kind, - raw: token.spelling.into_bytes().into_boxed_slice(), - }) - }) - .collect::>() - }) - } -} - -/// Checks whether the name looks like an identifier, i.e. is alphanumeric -/// (including '_') and does not start with a digit. -pub fn is_valid_identifier(name: &str) -> bool { - let mut chars = name.chars(); - let first_valid = chars - .next() - .map(|c| c.is_alphabetic() || c == '_') - .unwrap_or(false); - - first_valid && chars.all(|c| c.is_alphanumeric() || c == '_') -} - -extern "C" fn visit_children( - cur: CXCursor, - _parent: CXCursor, - data: CXClientData, -) -> CXChildVisitResult -where - Visitor: FnMut(Cursor) -> CXChildVisitResult, -{ - let func: &mut Visitor = unsafe { mem::transmute(data) }; - let child = Cursor { - x: cur, - }; - - (*func)(child) -} - -impl PartialEq for Cursor { - fn eq(&self, other: &Cursor) -> bool { - unsafe { clang_equalCursors(self.x, other.x) == 1 } - } -} - -impl Eq for Cursor {} - -impl Hash for Cursor { - fn hash(&self, state: &mut H) { - unsafe { clang_hashCursor(self.x) }.hash(state) - } -} - -/// The type of a node in clang's AST. -#[derive(Clone, Copy)] -pub struct Type { - x: CXType, -} - -impl PartialEq for Type { - fn eq(&self, other: &Self) -> bool { - unsafe { clang_equalTypes(self.x, other.x) != 0 } - } -} - -impl Eq for Type {} - -impl fmt::Debug for Type { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!( - fmt, - "Type({}, kind: {}, cconv: {}, decl: {:?}, canon: {:?})", - self.spelling(), - type_to_str(self.kind()), - self.call_conv(), - self.declaration(), - self.declaration().canonical() - ) - } -} - -/// An error about the layout of a struct, class, or type. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum LayoutError { - /// Asked for the layout of an invalid type. - Invalid, - /// Asked for the layout of an incomplete type. - Incomplete, - /// Asked for the layout of a dependent type. - Dependent, - /// Asked for the layout of a type that does not have constant size. - NotConstantSize, - /// Asked for the layout of a field in a type that does not have such a - /// field. - InvalidFieldName, - /// An unknown layout error. - Unknown, -} - -impl ::std::convert::From for LayoutError { - fn from(val: i32) -> Self { - use self::LayoutError::*; - - match val { - CXTypeLayoutError_Invalid => Invalid, - CXTypeLayoutError_Incomplete => Incomplete, - CXTypeLayoutError_Dependent => Dependent, - CXTypeLayoutError_NotConstantSize => NotConstantSize, - CXTypeLayoutError_InvalidFieldName => InvalidFieldName, - _ => Unknown, - } - } -} - -impl Type { - /// Get this type's kind. - pub fn kind(&self) -> CXTypeKind { - self.x.kind - } - - /// Get a cursor pointing to this type's declaration. - pub fn declaration(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getTypeDeclaration(self.x), - } - } - } - - /// Get the canonical declaration of this type, if it is available. - pub fn canonical_declaration( - &self, - location: Option<&Cursor>, - ) -> Option { - let mut declaration = self.declaration(); - if !declaration.is_valid() { - if let Some(location) = location { - let mut location = *location; - if let Some(referenced) = location.referenced() { - location = referenced; - } - if location.is_template_like() { - declaration = location; - } - } - } - - let canonical = declaration.canonical(); - if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound { - Some(CanonicalTypeDeclaration(*self, canonical)) - } else { - None - } - } - - /// Get a raw display name for this type. - pub fn spelling(&self) -> String { - let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) }; - // Clang 5.0 introduced changes in the spelling API so it returned the - // full qualified name. Let's undo that here. - if s.split("::").all(|s| is_valid_identifier(s)) { - if let Some(s) = s.split("::").last() { - return s.to_owned(); - } - } - - s - } - - /// Is this type const qualified? - pub fn is_const(&self) -> bool { - unsafe { clang_isConstQualifiedType(self.x) != 0 } - } - - /// What is the size of this type? Paper over invalid types by returning `0` - /// for them. - pub fn size(&self) -> usize { - unsafe { - let val = clang_Type_getSizeOf(self.x); - if val < 0 { 0 } else { val as usize } - } - } - - /// What is the size of this type? - pub fn fallible_size(&self) -> Result { - let val = unsafe { clang_Type_getSizeOf(self.x) }; - if val < 0 { - Err(LayoutError::from(val as i32)) - } else { - Ok(val as usize) - } - } - - /// What is the alignment of this type? Paper over invalid types by - /// returning `0`. - pub fn align(&self) -> usize { - unsafe { - let val = clang_Type_getAlignOf(self.x); - if val < 0 { 0 } else { val as usize } - } - } - - /// What is the alignment of this type? - pub fn fallible_align(&self) -> Result { - unsafe { - let val = clang_Type_getAlignOf(self.x); - if val < 0 { - Err(LayoutError::from(val as i32)) - } else { - Ok(val as usize) - } - } - } - - /// Get the layout for this type, or an error describing why it does not - /// have a valid layout. - pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> { - use ir::layout::Layout; - let size = self.fallible_size()?; - let align = self.fallible_align()?; - Ok(Layout::new(size, align)) - } - - /// Get the number of template arguments this type has, or `None` if it is - /// not some kind of template. - pub fn num_template_args(&self) -> Option { - let n = unsafe { clang_Type_getNumTemplateArguments(self.x) }; - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - } - - /// If this type is a class template specialization, return its - /// template arguments. Otherwise, return None. - pub fn template_args(&self) -> Option { - self.num_template_args().map(|n| { - TypeTemplateArgIterator { - x: self.x, - length: n, - index: 0, - } - }) - } - - /// Given that this type is a pointer type, return the type that it points - /// to. - pub fn pointee_type(&self) -> Option { - match self.kind() { - CXType_Pointer | - CXType_RValueReference | - CXType_LValueReference | - CXType_MemberPointer | - CXType_ObjCObjectPointer => { - let ret = Type { - x: unsafe { clang_getPointeeType(self.x) }, - }; - debug_assert!(ret.is_valid()); - Some(ret) - } - _ => None, - } - } - - /// Given that this type is an array, vector, or complex type, return the - /// type of its elements. - pub fn elem_type(&self) -> Option { - let current_type = Type { - x: unsafe { clang_getElementType(self.x) }, - }; - if current_type.is_valid() { - Some(current_type) - } else { - None - } - } - - /// Given that this type is an array or vector type, return its number of - /// elements. - pub fn num_elements(&self) -> Option { - let num_elements_returned = unsafe { clang_getNumElements(self.x) }; - if num_elements_returned != -1 { - Some(num_elements_returned as usize) - } else { - None - } - } - - /// Get the canonical version of this type. This sees through `typdef`s and - /// aliases to get the underlying, canonical type. - pub fn canonical_type(&self) -> Type { - unsafe { - Type { - x: clang_getCanonicalType(self.x), - } - } - } - - /// Is this type a variadic function type? - pub fn is_variadic(&self) -> bool { - unsafe { clang_isFunctionTypeVariadic(self.x) != 0 } - } - - /// Given that this type is a function type, get the type of its return - /// value. - pub fn ret_type(&self) -> Option { - let rt = Type { - x: unsafe { clang_getResultType(self.x) }, - }; - if rt.is_valid() { Some(rt) } else { None } - } - - /// Given that this type is a function type, get its calling convention. If - /// this is not a function type, `CXCallingConv_Invalid` is returned. - pub fn call_conv(&self) -> CXCallingConv { - unsafe { clang_getFunctionTypeCallingConv(self.x) } - } - - /// For elaborated types (types which use `class`, `struct`, or `union` to - /// disambiguate types from local bindings), get the underlying type. - pub fn named(&self) -> Type { - unsafe { - Type { - x: if clang_Type_getNamedType::is_loaded() { - clang_Type_getNamedType(self.x) - } else { - self.x - }, - } - } - } - - /// Is this a valid type? - pub fn is_valid(&self) -> bool { - self.kind() != CXType_Invalid - } - - /// Is this a valid and exposed type? - pub fn is_valid_and_exposed(&self) -> bool { - self.is_valid() && self.kind() != CXType_Unexposed - } - - /// Is this type a fully instantiated template? - pub fn is_fully_instantiated_template(&self) -> bool { - // Yep, the spelling of this containing type-parameter is extremely - // nasty... But can happen in . Unfortunately I couldn't - // reduce it enough :( - self.template_args().map_or(false, |args| args.len() > 0) && - match self.declaration().kind() { - CXCursor_ClassTemplatePartialSpecialization | - CXCursor_TypeAliasTemplateDecl | - CXCursor_TemplateTemplateParameter => false, - _ => true, - } - } - - /// Is this type an associated template type? Eg `T::Associated` in - /// this example: - /// - /// ```c++ - /// template - /// class Foo { - /// typename T::Associated member; - /// }; - /// ``` - pub fn is_associated_type(&self) -> bool { - // This is terrible :( - fn hacky_parse_associated_type>(spelling: S) -> bool { - lazy_static! { - static ref ASSOC_TYPE_RE: regex::Regex = - regex::Regex::new(r"typename type\-parameter\-\d+\-\d+::.+").unwrap(); - } - ASSOC_TYPE_RE.is_match(spelling.as_ref()) - } - - self.kind() == CXType_Unexposed && - (hacky_parse_associated_type(self.spelling()) || - hacky_parse_associated_type(self.canonical_type().spelling())) - } -} - -/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its -/// cursor is the canonical declaration for its type. If you have a -/// `CanonicalTypeDeclaration` instance, you know for sure that the type and -/// cursor match up in a canonical declaration relationship, and it simply -/// cannot be otherwise. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct CanonicalTypeDeclaration(Type, Cursor); - -impl CanonicalTypeDeclaration { - /// Get the type. - pub fn ty(&self) -> &Type { - &self.0 - } - - /// Get the type's canonical declaration cursor. - pub fn cursor(&self) -> &Cursor { - &self.1 - } -} - -/// An iterator for a type's template arguments. -pub struct TypeTemplateArgIterator { - x: CXType, - length: u32, - index: u32, -} - -impl Iterator for TypeTemplateArgIterator { - type Item = Type; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index as c_uint; - self.index += 1; - Some(Type { - x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) }, - }) - } else { - None - } - } -} - -impl ExactSizeIterator for TypeTemplateArgIterator { - fn len(&self) -> usize { - assert!(self.index <= self.length); - (self.length - self.index) as usize - } -} - -/// A `SourceLocation` is a file, line, column, and byte offset location for -/// some source text. -pub struct SourceLocation { - x: CXSourceLocation, -} - -impl SourceLocation { - /// Get the (file, line, column, byte offset) tuple for this source - /// location. - pub fn location(&self) -> (File, usize, usize, usize) { - unsafe { - let mut file = mem::zeroed(); - let mut line = 0; - let mut col = 0; - let mut off = 0; - clang_getSpellingLocation( - self.x, - &mut file, - &mut line, - &mut col, - &mut off, - ); - ( - File { - x: file, - }, - line as usize, - col as usize, - off as usize, - ) - } - } -} - -impl fmt::Display for SourceLocation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (file, line, col, _) = self.location(); - if let Some(name) = file.name() { - write!(f, "{}:{}:{}", name, line, col) - } else { - "builtin definitions".fmt(f) - } - } -} - -/// A comment in the source text. -/// -/// Comments are sort of parsed by Clang, and have a tree structure. -pub struct Comment { - x: CXComment, -} - -impl Comment { - /// What kind of comment is this? - pub fn kind(&self) -> CXCommentKind { - unsafe { clang_Comment_getKind(self.x) } - } - - /// Get this comment's children comment - pub fn get_children(&self) -> CommentChildrenIterator { - CommentChildrenIterator { - parent: self.x, - length: unsafe { clang_Comment_getNumChildren(self.x) }, - index: 0, - } - } - - /// Given that this comment is the start or end of an HTML tag, get its tag - /// name. - pub fn get_tag_name(&self) -> String { - unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) } - } - - /// Given that this comment is an HTML start tag, get its attributes. - pub fn get_tag_attrs(&self) -> CommentAttributesIterator { - CommentAttributesIterator { - x: self.x, - length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) }, - index: 0, - } - } -} - -/// An iterator for a comment's children -pub struct CommentChildrenIterator { - parent: CXComment, - length: c_uint, - index: c_uint, -} - -impl Iterator for CommentChildrenIterator { - type Item = Comment; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index; - self.index += 1; - Some(Comment { - x: unsafe { clang_Comment_getChild(self.parent, idx) }, - }) - } else { - None - } - } -} - -/// An HTML start tag comment attribute -pub struct CommentAttribute { - /// HTML start tag attribute name - pub name: String, - /// HTML start tag attribute value - pub value: String, -} - -/// An iterator for a comment's attributes -pub struct CommentAttributesIterator { - x: CXComment, - length: c_uint, - index: c_uint, -} - -impl Iterator for CommentAttributesIterator { - type Item = CommentAttribute; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index; - self.index += 1; - Some(CommentAttribute { - name: unsafe { - cxstring_into_string( - clang_HTMLStartTag_getAttrName(self.x, idx), - ) - }, - value: unsafe { - cxstring_into_string( - clang_HTMLStartTag_getAttrValue(self.x, idx), - ) - }, - }) - } else { - None - } - } -} - -/// A source file. -pub struct File { - x: CXFile, -} - -impl File { - /// Get the name of this source file. - pub fn name(&self) -> Option { - if self.x.is_null() { - return None; - } - Some(unsafe { cxstring_into_string(clang_getFileName(self.x)) }) - } -} - -fn cxstring_to_string_leaky(s: CXString) -> String { - if s.data.is_null() { - return "".to_owned(); - } - let c_str = unsafe { CStr::from_ptr(clang_getCString(s) as *const _) }; - c_str.to_string_lossy().into_owned() -} - -fn cxstring_into_string(s: CXString) -> String { - let ret = cxstring_to_string_leaky(s); - unsafe { clang_disposeString(s) }; - ret -} - -/// An `Index` is an environment for a set of translation units that will -/// typically end up linked together in one final binary. -pub struct Index { - x: CXIndex, -} - -impl Index { - /// Construct a new `Index`. - /// - /// The `pch` parameter controls whether declarations in pre-compiled - /// headers are included when enumerating a translation unit's "locals". - /// - /// The `diag` parameter controls whether debugging diagnostics are enabled. - pub fn new(pch: bool, diag: bool) -> Index { - unsafe { - Index { - x: clang_createIndex(pch as c_int, diag as c_int), - } - } - } -} - -impl fmt::Debug for Index { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "Index {{ }}") - } -} - -impl Drop for Index { - fn drop(&mut self) { - unsafe { - clang_disposeIndex(self.x); - } - } -} - -/// A token emitted by clang's lexer. -#[derive(Debug)] -pub struct Token { - /// The kind of token this is. - pub kind: CXTokenKind, - /// A display name for this token. - pub spelling: String, -} - -/// A translation unit (or "compilation unit"). -pub struct TranslationUnit { - x: CXTranslationUnit, -} - -impl fmt::Debug for TranslationUnit { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "TranslationUnit {{ }}") - } -} - -impl TranslationUnit { - /// Parse a source file into a translation unit. - pub fn parse( - ix: &Index, - file: &str, - cmd_args: &[String], - unsaved: &[UnsavedFile], - opts: CXTranslationUnit_Flags, - ) -> Option { - let fname = CString::new(file).unwrap(); - let _c_args: Vec = cmd_args - .iter() - .map(|s| CString::new(s.clone()).unwrap()) - .collect(); - let c_args: Vec<*const c_char> = - _c_args.iter().map(|s| s.as_ptr()).collect(); - let mut c_unsaved: Vec = - unsaved.iter().map(|f| f.x).collect(); - let tu = unsafe { - clang_parseTranslationUnit( - ix.x, - fname.as_ptr(), - c_args.as_ptr(), - c_args.len() as c_int, - c_unsaved.as_mut_ptr(), - c_unsaved.len() as c_uint, - opts, - ) - }; - if tu.is_null() { - None - } else { - Some(TranslationUnit { - x: tu, - }) - } - } - - /// Get the Clang diagnostic information associated with this translation - /// unit. - pub fn diags(&self) -> Vec { - unsafe { - let num = clang_getNumDiagnostics(self.x) as usize; - let mut diags = vec![]; - for i in 0..num { - diags.push(Diagnostic { - x: clang_getDiagnostic(self.x, i as c_uint), - }); - } - diags - } - } - - /// Get a cursor pointing to the root of this translation unit's AST. - pub fn cursor(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getTranslationUnitCursor(self.x), - } - } - } - - /// Is this the null translation unit? - pub fn is_null(&self) -> bool { - self.x.is_null() - } -} - -impl Drop for TranslationUnit { - fn drop(&mut self) { - unsafe { - clang_disposeTranslationUnit(self.x); - } - } -} - - -/// A diagnostic message generated while parsing a translation unit. -pub struct Diagnostic { - x: CXDiagnostic, -} - -impl Diagnostic { - /// Format this diagnostic message as a string, using the given option bit - /// flags. - pub fn format(&self) -> String { - unsafe { - let opts = clang_defaultDiagnosticDisplayOptions(); - cxstring_into_string(clang_formatDiagnostic(self.x, opts)) - } - } - - /// What is the severity of this diagnostic message? - pub fn severity(&self) -> CXDiagnosticSeverity { - unsafe { clang_getDiagnosticSeverity(self.x) } - } -} - -impl Drop for Diagnostic { - /// Destroy this diagnostic message. - fn drop(&mut self) { - unsafe { - clang_disposeDiagnostic(self.x); - } - } -} - -/// A file which has not been saved to disk. -pub struct UnsavedFile { - x: CXUnsavedFile, - /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in - /// `CXUnsavedFile`. - pub name: CString, - contents: CString, -} - -impl UnsavedFile { - /// Construct a new unsaved file with the given `name` and `contents`. - pub fn new(name: &str, contents: &str) -> UnsavedFile { - let name = CString::new(name).unwrap(); - let contents = CString::new(contents).unwrap(); - let x = CXUnsavedFile { - Filename: name.as_ptr(), - Contents: contents.as_ptr(), - Length: contents.as_bytes().len() as c_ulong, - }; - UnsavedFile { - x: x, - name: name, - contents: contents, - } - } -} - -impl fmt::Debug for UnsavedFile { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!( - fmt, - "UnsavedFile(name: {:?}, contents: {:?})", - self.name, - self.contents - ) - } -} - -/// Convert a cursor kind into a static string. -pub fn kind_to_str(x: CXCursorKind) -> String { - unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) } -} - -/// Convert a type kind to a static string. -pub fn type_to_str(x: CXTypeKind) -> String { - unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) } -} - -/// Dump the Clang AST to stdout for debugging purposes. -pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult { - fn print_indent>(depth: isize, s: S) { - for _ in 0..depth { - print!(" "); - } - println!("{}", s.as_ref()); - } - - fn print_cursor>(depth: isize, prefix: S, c: &Cursor) { - let prefix = prefix.as_ref(); - print_indent( - depth, - format!(" {}kind = {}", prefix, kind_to_str(c.kind())), - ); - print_indent( - depth, - format!(" {}spelling = \"{}\"", prefix, c.spelling()), - ); - print_indent(depth, format!(" {}location = {}", prefix, c.location())); - print_indent( - depth, - format!(" {}is-definition? {}", prefix, c.is_definition()), - ); - print_indent( - depth, - format!(" {}is-declaration? {}", prefix, c.is_declaration()), - ); - print_indent( - depth, - format!( - " {}is-inlined-function? {}", - prefix, - c.is_inlined_function() - ), - ); - - let templ_kind = c.template_kind(); - if templ_kind != CXCursor_NoDeclFound { - print_indent( - depth, - format!(" {}template-kind = {}", prefix, kind_to_str(templ_kind)), - ); - } - if let Some(usr) = c.usr() { - print_indent(depth, format!(" {}usr = \"{}\"", prefix, usr)); - } - if let Ok(num) = c.num_args() { - print_indent(depth, format!(" {}number-of-args = {}", prefix, num)); - } - if let Some(num) = c.num_template_args() { - print_indent( - depth, - format!(" {}number-of-template-args = {}", prefix, num), - ); - } - if let Some(width) = c.bit_width() { - print_indent(depth, format!(" {}bit-width = {}", prefix, width)); - } - if let Some(ty) = c.enum_type() { - print_indent( - depth, - format!(" {}enum-type = {}", prefix, type_to_str(ty.kind())), - ); - } - if let Some(val) = c.enum_val_signed() { - print_indent(depth, format!(" {}enum-val = {}", prefix, val)); - } - if let Some(ty) = c.typedef_type() { - print_indent( - depth, - format!(" {}typedef-type = {}", prefix, type_to_str(ty.kind())), - ); - } - if let Some(ty) = c.ret_type() { - print_indent( - depth, - format!(" {}ret-type = {}", prefix, type_to_str(ty.kind())), - ); - } - - if let Some(refd) = c.referenced() { - if refd != *c { - println!(""); - print_cursor( - depth, - String::from(prefix) + "referenced.", - &refd, - ); - } - } - - let canonical = c.canonical(); - if canonical != *c { - println!(""); - print_cursor( - depth, - String::from(prefix) + "canonical.", - &canonical, - ); - } - - if let Some(specialized) = c.specialized() { - if specialized != *c { - println!(""); - print_cursor( - depth, - String::from(prefix) + "specialized.", - &specialized, - ); - } - } - - if let Some(parent) = c.fallible_semantic_parent() { - println!(""); - print_cursor( - depth, - String::from(prefix) + "semantic-parent.", - &parent, - ); - } - } - - fn print_type>(depth: isize, prefix: S, ty: &Type) { - let prefix = prefix.as_ref(); - - let kind = ty.kind(); - print_indent(depth, format!(" {}kind = {}", prefix, type_to_str(kind))); - if kind == CXType_Invalid { - return; - } - - print_indent(depth, format!(" {}cconv = {}", prefix, ty.call_conv())); - - print_indent( - depth, - format!(" {}spelling = \"{}\"", prefix, ty.spelling()), - ); - let num_template_args = - unsafe { clang_Type_getNumTemplateArguments(ty.x) }; - if num_template_args >= 0 { - print_indent( - depth, - format!( - " {}number-of-template-args = {}", - prefix, - num_template_args - ), - ); - } - if let Some(num) = ty.num_elements() { - print_indent( - depth, - format!(" {}number-of-elements = {}", prefix, num), - ); - } - print_indent( - depth, - format!(" {}is-variadic? {}", prefix, ty.is_variadic()), - ); - - let canonical = ty.canonical_type(); - if canonical != *ty { - println!(""); - print_type(depth, String::from(prefix) + "canonical.", &canonical); - } - - if let Some(pointee) = ty.pointee_type() { - if pointee != *ty { - println!(""); - print_type(depth, String::from(prefix) + "pointee.", &pointee); - } - } - - if let Some(elem) = ty.elem_type() { - if elem != *ty { - println!(""); - print_type(depth, String::from(prefix) + "elements.", &elem); - } - } - - if let Some(ret) = ty.ret_type() { - if ret != *ty { - println!(""); - print_type(depth, String::from(prefix) + "return.", &ret); - } - } - - let named = ty.named(); - if named != *ty && named.is_valid() { - println!(""); - print_type(depth, String::from(prefix) + "named.", &named); - } - } - - print_indent(depth, "("); - print_cursor(depth, "", c); - - println!(""); - let ty = c.cur_type(); - print_type(depth, "type.", &ty); - - let declaration = ty.declaration(); - if declaration != *c && declaration.kind() != CXCursor_NoDeclFound { - println!(""); - print_cursor(depth, "type.declaration.", &declaration); - } - - // Recurse. - let mut found_children = false; - c.visit(|s| { - if !found_children { - println!(""); - found_children = true; - } - ast_dump(&s, depth + 1) - }); - - print_indent(depth, ")"); - - CXChildVisit_Continue -} - -/// Try to extract the clang version to a string -pub fn extract_clang_version() -> String { - unsafe { cxstring_into_string(clang_getClangVersion()) } -} - -/// A wrapper for the result of evaluating an expression. -#[derive(Debug)] -pub struct EvalResult { - x: CXEvalResult, -} - -impl EvalResult { - /// Evaluate `cursor` and return the result. - pub fn new(cursor: Cursor) -> Option { - if !clang_Cursor_Evaluate::is_loaded() { - return None; - } - - // Clang has an internal assertion we can trigger if we try to evaluate - // a cursor containing a variadic template type reference. Triggering - // the assertion aborts the process, and we don't want that. Clang - // *also* doesn't expose any API for finding variadic vs non-variadic - // template type references, let alone whether a type referenced is a - // template type, instead they seem to show up as type references to an - // unexposed type. Our solution is to just flat out ban all - // `CXType_Unexposed` from evaluation. - let mut found_cant_eval = false; - cursor.visit(|c| if c.kind() == CXCursor_TypeRef && - c.cur_type().kind() == CXType_Unexposed - { - found_cant_eval = true; - CXChildVisit_Break - } else { - CXChildVisit_Recurse - }); - if found_cant_eval { - return None; - } - - Some(EvalResult { - x: unsafe { clang_Cursor_Evaluate(cursor.x) }, - }) - } - - fn kind(&self) -> CXEvalResultKind { - unsafe { clang_EvalResult_getKind(self.x) } - } - - /// Try to get back the result as a double. - pub fn as_double(&self) -> Option { - match self.kind() { - CXEval_Float => { - Some(unsafe { clang_EvalResult_getAsDouble(self.x) } as f64) - } - _ => None, - } - } - - /// Try to get back the result as an integer. - pub fn as_int(&self) -> Option { - match self.kind() { - CXEval_Int => { - Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32) - } - _ => None, - } - } - - /// Evaluates the expression as a literal string, that may or may not be - /// valid utf-8. - pub fn as_literal_string(&self) -> Option> { - match self.kind() { - CXEval_StrLiteral => { - let ret = unsafe { - CStr::from_ptr(clang_EvalResult_getAsStr(self.x)) - }; - Some(ret.to_bytes().to_vec()) - } - _ => None, - } - } -} - -impl Drop for EvalResult { - fn drop(&mut self) { - unsafe { clang_EvalResult_dispose(self.x) }; - } -} - -/// Target information obtained from libclang. -#[derive(Debug)] -pub struct TargetInfo { - /// The target triple. - pub triple: String, - /// The width of the pointer _in bits_. - pub pointer_width: usize, -} - -impl TargetInfo { - /// Tries to obtain target information from libclang. - pub fn new(tu: &TranslationUnit) -> Option { - if !clang_getTranslationUnitTargetInfo::is_loaded() { - return None; - } - let triple; - let pointer_width; - unsafe { - let ti = clang_getTranslationUnitTargetInfo(tu.x); - triple = cxstring_into_string(clang_TargetInfo_getTriple(ti)); - pointer_width = clang_TargetInfo_getPointerWidth(ti); - clang_TargetInfo_dispose(ti); - } - assert!(pointer_width > 0); - assert_eq!(pointer_width % 8, 0); - Some(TargetInfo { - triple, - pointer_width: pointer_width as usize, - }) - } -} diff --git a/src/codegen/bitfield_unit.rs b/src/codegen/bitfield_unit.rs deleted file mode 100755 index 3c7c9b7b8b..0000000000 --- a/src/codegen/bitfield_unit.rs +++ /dev/null @@ -1,82 +0,0 @@ -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { - storage, - align: [], - } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} diff --git a/src/codegen/error.rs b/src/codegen/error.rs deleted file mode 100644 index ccb76c5bd7..0000000000 --- a/src/codegen/error.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::error; -use std::fmt; - -/// Errors that can occur during code generation. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Error { - /// Tried to generate an opaque blob for a type that did not have a layout. - NoLayoutForOpaqueBlob, - - /// Tried to instantiate an opaque template definition, or a template - /// definition that is too difficult for us to understand (like a partial - /// template specialization). - InstantiationOfOpaqueType, -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", error::Error::description(self)) - } -} - -impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { - None - } - - fn description(&self) -> &'static str { - match *self { - Error::NoLayoutForOpaqueBlob => { - "Tried to generate an opaque blob, but had no layout" - } - Error::InstantiationOfOpaqueType => { - "Instantiation of opaque template type or partial template \ - specialization" - } - } - } -} - -/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`. -pub type Result = ::std::result::Result; diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs deleted file mode 100644 index f1007c51e6..0000000000 --- a/src/codegen/helpers.rs +++ /dev/null @@ -1,253 +0,0 @@ -//! Helpers for code generation that don't need macro expansion. - -use ir::context::BindgenContext; -use ir::layout::Layout; -use quote; -use std::mem; -use proc_macro2::{Term, Span}; - -pub mod attributes { - use quote; - use proc_macro2::{Term, Span}; - - pub fn repr(which: &str) -> quote::Tokens { - let which = Term::new(which, Span::call_site()); - quote! { - #[repr( #which )] - } - } - - pub fn repr_list(which_ones: &[&str]) -> quote::Tokens { - let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site())); - quote! { - #[repr( #( #which_ones ),* )] - } - } - - pub fn derives(which_ones: &[&str]) -> quote::Tokens { - let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site())); - quote! { - #[derive( #( #which_ones ),* )] - } - } - - pub fn inline() -> quote::Tokens { - quote! { - #[inline] - } - } - - pub fn doc(comment: String) -> quote::Tokens { - // Doc comments are already preprocessed into nice `///` formats by the - // time they get here. Just make sure that we have newlines around it so - // that nothing else gets wrapped into the comment. - let mut tokens = quote! {}; - tokens.append(Term::new("\n", Span::call_site())); - tokens.append(Term::new(&comment, Span::call_site())); - tokens.append(Term::new("\n", Span::call_site())); - tokens - } - - pub fn link_name(name: &str) -> quote::Tokens { - // LLVM mangles the name by default but it's already mangled. - // Prefixing the name with \u{1} should tell LLVM to not mangle it. - let name = format!("\u{1}{}", name); - quote! { - #[link_name = #name] - } - } -} - -/// Generates a proper type for a field or type with a given `Layout`, that is, -/// a type with the correct size and alignment restrictions. -pub fn blob(layout: Layout) -> quote::Tokens { - let opaque = layout.opaque(); - - // FIXME(emilio, #412): We fall back to byte alignment, but there are - // some things that legitimately are more than 8-byte aligned. - // - // Eventually we should be able to `unwrap` here, but... - let ty_name = match opaque.known_rust_type_for_array() { - Some(ty) => ty, - None => { - warn!("Found unknown alignment on code generation!"); - "u8" - } - }; - - let ty_name = Term::new(ty_name, Span::call_site()); - - let data_len = opaque.array_size().unwrap_or(layout.size); - - if data_len == 1 { - quote! { - #ty_name - } - } else { - quote! { - [ #ty_name ; #data_len ] - } - } -} - -/// Integer type of the same size as the given `Layout`. -pub fn integer_type(layout: Layout) -> Option { - // This guard can be weakened when Rust implements u128. - if layout.size > mem::size_of::() { - None - } else { - Some(blob(layout)) - } -} - -/// Generates a bitfield allocation unit type for a type with the given `Layout`. -pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens { - let mut tokens = quote! {}; - - if ctx.options().enable_cxx_namespaces { - tokens.append_all(quote! { root:: }); - } - - let align = match layout.align { - n if n >= 8 => quote! { u64 }, - 4 => quote! { u32 }, - 2 => quote! { u16 }, - _ => quote! { u8 }, - }; - - let size = layout.size; - tokens.append_all(quote! { - __BindgenBitfieldUnit<[u8; #size], #align> - }); - - tokens -} - -pub mod ast_ty { - use ir::context::BindgenContext; - use ir::function::FunctionSig; - use ir::ty::FloatKind; - use quote; - use proc_macro2; - - pub fn raw_type(ctx: &BindgenContext, name: &str) -> quote::Tokens { - let ident = ctx.rust_ident_raw(name); - match ctx.options().ctypes_prefix { - Some(ref prefix) => { - let prefix = ctx.rust_ident_raw(prefix.as_str()); - quote! { - #prefix::#ident - } - } - None => quote! { - ::std::os::raw::#ident - }, - } - } - - pub fn float_kind_rust_type( - ctx: &BindgenContext, - fk: FloatKind, - ) -> quote::Tokens { - // TODO: we probably should just take the type layout into - // account? - // - // Also, maybe this one shouldn't be the default? - // - // FIXME: `c_longdouble` doesn't seem to be defined in some - // systems, so we use `c_double` directly. - match (fk, ctx.options().convert_floats) { - (FloatKind::Float, true) => quote! { f32 }, - (FloatKind::Double, true) | - (FloatKind::LongDouble, true) => quote! { f64 }, - (FloatKind::Float, false) => raw_type(ctx, "c_float"), - (FloatKind::Double, false) | - (FloatKind::LongDouble, false) => raw_type(ctx, "c_double"), - (FloatKind::Float128, _) => quote! { [u8; 16] }, - } - } - - pub fn int_expr(val: i64) -> quote::Tokens { - // Don't use quote! { #val } because that adds the type suffix. - let val = proc_macro2::Literal::i64_unsuffixed(val); - quote!(#val) - } - - pub fn uint_expr(val: u64) -> quote::Tokens { - // Don't use quote! { #val } because that adds the type suffix. - let val = proc_macro2::Literal::u64_unsuffixed(val); - quote!(#val) - } - - pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens { - let mut bytes: Vec<_> = bytes.iter().cloned().collect(); - bytes.push(0); - quote! { [ #(#bytes),* ] } - } - - pub fn cstr_expr(mut string: String) -> quote::Tokens { - string.push('\0'); - let b = proc_macro2::Literal::byte_string(&string.as_bytes()); - quote! { - #b - } - } - - pub fn float_expr( - ctx: &BindgenContext, - f: f64, - ) -> Result { - if f.is_finite() { - let val = proc_macro2::Literal::f64_unsuffixed(f); - - return Ok(quote!(#val)); - } - - let prefix = ctx.trait_prefix(); - - if f.is_nan() { - return Ok(quote! { - ::#prefix::f64::NAN - }); - } - - if f.is_infinite() { - return Ok(if f.is_sign_positive() { - quote! { - ::#prefix::f64::INFINITY - } - } else { - quote! { - ::#prefix::f64::NEG_INFINITY - } - }); - } - - warn!("Unknown non-finite float number: {:?}", f); - return Err(()); - } - - pub fn arguments_from_signature( - signature: &FunctionSig, - ctx: &BindgenContext, - ) -> Vec { - let mut unnamed_arguments = 0; - signature - .argument_types() - .iter() - .map(|&(ref name, _ty)| { - match *name { - Some(ref name) => { - let name = ctx.rust_ident(name); - quote! { #name } - } - None => { - unnamed_arguments += 1; - let name = ctx.rust_ident(format!("arg{}", unnamed_arguments)); - quote! { #name } - } - } - }) - .collect() - } -} diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs deleted file mode 100644 index ab934ed6cc..0000000000 --- a/src/codegen/impl_debug.rs +++ /dev/null @@ -1,222 +0,0 @@ -use ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods}; -use ir::context::BindgenContext; -use ir::derive::CanTriviallyDeriveDebug; -use ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName}; -use ir::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, TypeKind}; -use quote; - -pub fn gen_debug_impl( - ctx: &BindgenContext, - fields: &[Field], - item: &Item, - kind: CompKind, -) -> quote::Tokens { - let struct_name = item.canonical_name(ctx); - let mut format_string = format!("{} {{{{ ", struct_name); - let mut tokens = vec![]; - - if item.is_opaque(ctx, &()) { - format_string.push_str("opaque"); - } else { - match kind { - CompKind::Union => { - format_string.push_str("union"); - } - CompKind::Struct => { - let processed_fields = fields.iter().filter_map(|f| match f { - &Field::DataMember(ref fd) => fd.impl_debug(ctx, ()), - &Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()), - }); - - for (i, (fstring, toks)) in processed_fields.enumerate() { - if i > 0 { - format_string.push_str(", "); - } - tokens.extend(toks); - format_string.push_str(&fstring); - } - } - } - } - - format_string.push_str(" }}"); - tokens.insert(0, quote! { #format_string }); - - quote! { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, #( #tokens ),*) - } - } -} - -/// A trait for the things which we can codegen tokens that contribute towards a -/// generated `impl Debug`. -pub trait ImplDebug<'a> { - /// Any extra parameter required by this a particular `ImplDebug` implementation. - type Extra; - - /// Generate a format string snippet to be included in the larger `impl Debug` - /// format string, and the code to get the format string's interpolation values. - fn impl_debug( - &self, - ctx: &BindgenContext, - extra: Self::Extra, - ) -> Option<(String, Vec)>; -} - -impl<'a> ImplDebug<'a> for FieldData { - type Extra = (); - - fn impl_debug( - &self, - ctx: &BindgenContext, - _: Self::Extra, - ) -> Option<(String, Vec)> { - if let Some(name) = self.name() { - ctx.resolve_item(self.ty()).impl_debug(ctx, name) - } else { - None - } - } -} - -impl<'a> ImplDebug<'a> for BitfieldUnit { - type Extra = (); - - fn impl_debug( - &self, - ctx: &BindgenContext, - _: Self::Extra, - ) -> Option<(String, Vec)> { - let mut format_string = String::new(); - let mut tokens = vec![]; - for (i, bitfield) in self.bitfields().iter().enumerate() { - if i > 0 { - format_string.push_str(", "); - } - - if let Some(bitfield_name) = bitfield.name() { - format_string.push_str(&format!("{} : {{:?}}", bitfield_name)); - let getter_name = bitfield.getter_name(); - let name_ident = ctx.rust_ident_raw(getter_name); - tokens.push(quote! { - self.#name_ident () - }); - } - } - - Some((format_string, tokens)) - } -} - -impl<'a> ImplDebug<'a> for Item { - type Extra = &'a str; - - fn impl_debug( - &self, - ctx: &BindgenContext, - name: &str, - ) -> Option<(String, Vec)> { - let name_ident = ctx.rust_ident(name); - - // We don't know if blacklisted items `impl Debug` or not, so we can't - // add them to the format string we're building up. - if !ctx.whitelisted_items().contains(&self.id()) { - return None; - } - - let ty = match self.as_type() { - Some(ty) => ty, - None => { - return None; - } - }; - - fn debug_print( - name: &str, - name_ident: quote::Tokens, - ) -> Option<(String, Vec)> { - Some(( - format!("{}: {{:?}}", name), - vec![quote! { - self.#name_ident - }], - )) - } - - match *ty.kind() { - // Handle the simple cases. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::BlockPointer | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::Comp(..) | - TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }), - - TypeKind::TemplateInstantiation(ref inst) => { - if inst.is_opaque(ctx, self) { - Some((format!("{}: opaque", name), vec![])) - } else { - debug_print(name, quote! { #name_ident }) - } - } - - // The generic is not required to implement Debug, so we can not debug print that type - TypeKind::TypeParam => { - Some((format!("{}: Non-debuggable generic", name), vec![])) - } - - TypeKind::Array(_, len) => { - // Generics are not required to implement Debug - if self.has_type_param_in_array(ctx) { - Some( - (format!("{}: Array with length {}", name, len), vec![]), - ) - } else if len < RUST_DERIVE_IN_ARRAY_LIMIT { - // The simple case - debug_print(name, quote! { #name_ident }) - } else { - // Let's implement our own print function - Some(( - format!("{}: [{{}}]", name), - vec![quote! { - self.#name_ident - .iter() - .enumerate() - .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) - .collect::() - }], - )) - } - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - // We follow the aliases - ctx.resolve_item(t).impl_debug(ctx, name) - } - - TypeKind::Pointer(inner) => { - let inner_type = ctx.resolve_type(inner).canonical_type(ctx); - match *inner_type.kind() { - TypeKind::Function(ref sig) - if !sig.can_trivially_derive_debug() => { - Some((format!("{}: FunctionPointer", name), vec![])) - } - _ => debug_print(name, quote! { #name_ident }), - } - } - - TypeKind::Opaque => None, - } - } -} diff --git a/src/codegen/impl_partialeq.rs b/src/codegen/impl_partialeq.rs deleted file mode 100644 index a05c65e7ff..0000000000 --- a/src/codegen/impl_partialeq.rs +++ /dev/null @@ -1,126 +0,0 @@ - -use ir::comp::{CompInfo, CompKind, Field, FieldMethods}; -use ir::context::BindgenContext; -use ir::item::{IsOpaque, Item}; -use ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT}; -use quote; -use proc_macro2; - -/// Generate a manual implementation of `PartialEq` trait for the -/// specified compound type. -pub fn gen_partialeq_impl( - ctx: &BindgenContext, - comp_info: &CompInfo, - item: &Item, - ty_for_impl: "e::Tokens, -) -> Option { - let mut tokens = vec![]; - - if item.is_opaque(ctx, &()) { - tokens.push(quote! { - &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..] - }); - } else if comp_info.kind() == CompKind::Union { - assert!(!ctx.options().rust_features().untagged_union); - tokens.push(quote! { - &self.bindgen_union_field[..] == &other.bindgen_union_field[..] - }); - } else { - for base in comp_info.base_members().iter() { - if !base.requires_storage(ctx) { - continue; - } - - let ty_item = ctx.resolve_item(base.ty); - let field_name = &base.field_name; - - if ty_item.is_opaque(ctx, &()) { - let field_name = ctx.rust_ident(field_name); - tokens.push(quote! { - &self. #field_name [..] == &other. #field_name [..] - }); - } else { - tokens.push(gen_field(ctx, ty_item, field_name)); - } - } - - for field in comp_info.fields() { - match *field { - Field::DataMember(ref fd) => { - let ty_item = ctx.resolve_item(fd.ty()); - let name = fd.name().unwrap(); - tokens.push(gen_field(ctx, ty_item, name)); - } - Field::Bitfields(ref bu) => for bitfield in bu.bitfields() { - if let Some(_) = bitfield.name() { - let getter_name = bitfield.getter_name(); - let name_ident = ctx.rust_ident_raw(getter_name); - tokens.push(quote! { - self.#name_ident () == other.#name_ident () - }); - } - }, - } - } - } - - Some(quote! { - fn eq(&self, other: & #ty_for_impl) -> bool { - #( #tokens )&&* - } - }) -} - -fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens { - fn quote_equals(name_ident: proc_macro2::Term) -> quote::Tokens { - quote! { self.#name_ident == other.#name_ident } - } - - let name_ident = ctx.rust_ident(name); - let ty = ty_item.expect_type(); - - match *ty.kind() { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Complex(..) | - TypeKind::Float(..) | - TypeKind::Enum(..) | - TypeKind::TypeParam | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::BlockPointer | - TypeKind::Reference(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::Comp(..) | - TypeKind::Pointer(_) | - TypeKind::Function(..) | - TypeKind::Opaque => quote_equals(name_ident), - - TypeKind::TemplateInstantiation(ref inst) => { - if inst.is_opaque(ctx, &ty_item) { - quote! { - &self. #name_ident [..] == &other. #name_ident [..] - } - } else { - quote_equals(name_ident) - } - } - - TypeKind::Array(_, len) => if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - quote_equals(name_ident) - } else { - quote! { - &self. #name_ident [..] == &other. #name_ident [..] - } - }, - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - let inner_item = ctx.resolve_item(t); - gen_field(ctx, inner_item, name) - } - } -} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs deleted file mode 100644 index 6483412ed5..0000000000 --- a/src/codegen/mod.rs +++ /dev/null @@ -1,3826 +0,0 @@ -mod impl_debug; -mod impl_partialeq; -mod error; -mod helpers; -pub mod struct_layout; - -#[cfg(test)] -#[allow(warnings)] -pub(crate) mod bitfield_unit; -#[cfg(test)] -mod bitfield_unit_tests; - -use self::helpers::attributes; -use self::struct_layout::StructLayoutTracker; - -use super::BindgenOptions; - -use ir::analysis::{HasVtable, Sizedness}; -use ir::annotations::FieldAccessorKind; -use ir::comment; -use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, - FieldData, FieldMethods, Method, MethodKind}; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, - CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq, CanDerive}; -use ir::dot; -use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; -use ir::function::{Abi, Function, FunctionKind, FunctionSig, Linkage}; -use ir::int::IntKind; -use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath}; -use ir::item_kind::ItemKind; -use ir::layout::Layout; -use ir::module::Module; -use ir::objc::{ObjCInterface, ObjCMethod}; -use ir::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters}; -use ir::ty::{Type, TypeKind}; -use ir::var::Var; - -use quote; -use proc_macro2::{self, Term, Span}; - -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::{HashSet, VecDeque}; -use std::collections::hash_map::{Entry, HashMap}; -use std::fmt::Write; -use std::iter; -use std::ops; - -// Name of type defined in constified enum module -pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type"; - -fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec { - let mut path = vec![quote! { self }]; - - if ctx.options().enable_cxx_namespaces { - for _ in 0..item.codegen_depth(ctx) { - path.push(quote! { super }); - } - } - - path -} - -fn root_import(ctx: &BindgenContext, module: &Item) -> quote::Tokens { - assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up"); - assert!(module.is_module()); - - let mut path = top_level_path(ctx, module); - - let root = ctx.root_module().canonical_name(ctx); - let root_ident = ctx.rust_ident(&root); - path.push(quote! { #root_ident }); - - - let mut tokens = quote! {}; - tokens.append_separated(path, Term::new("::", Span::call_site())); - - quote! { - #[allow(unused_imports)] - use #tokens ; - } -} - -struct CodegenResult<'a> { - items: Vec, - - /// A monotonic counter used to add stable unique id's to stuff that doesn't - /// need to be referenced by anything. - codegen_id: &'a Cell, - - /// Whether a bindgen union has been generated at least once. - saw_bindgen_union: bool, - - /// Whether an union has been generated at least once. - saw_union: bool, - - /// Whether an incomplete array has been generated at least once. - saw_incomplete_array: bool, - - /// Whether Objective C types have been seen at least once. - saw_objc: bool, - - /// Whether a bitfield allocation unit has been seen at least once. - saw_bitfield_unit: bool, - - items_seen: HashSet, - /// The set of generated function/var names, needed because in C/C++ is - /// legal to do something like: - /// - /// ```c++ - /// extern "C" { - /// void foo(); - /// extern int bar; - /// } - /// - /// extern "C" { - /// void foo(); - /// extern int bar; - /// } - /// ``` - /// - /// Being these two different declarations. - functions_seen: HashSet, - vars_seen: HashSet, - - /// Used for making bindings to overloaded functions. Maps from a canonical - /// function name to the number of overloads we have already codegen'd for - /// that name. This lets us give each overload a unique suffix. - overload_counters: HashMap, -} - -impl<'a> CodegenResult<'a> { - fn new(codegen_id: &'a Cell) -> Self { - CodegenResult { - items: vec![], - saw_union: false, - saw_bindgen_union: false, - saw_incomplete_array: false, - saw_objc: false, - saw_bitfield_unit: false, - codegen_id: codegen_id, - items_seen: Default::default(), - functions_seen: Default::default(), - vars_seen: Default::default(), - overload_counters: Default::default(), - } - } - - fn saw_union(&mut self) { - self.saw_union = true; - } - - fn saw_bindgen_union(&mut self) { - self.saw_union(); - self.saw_bindgen_union = true; - } - - fn saw_incomplete_array(&mut self) { - self.saw_incomplete_array = true; - } - - fn saw_objc(&mut self) { - self.saw_objc = true; - } - - fn saw_bitfield_unit(&mut self) { - self.saw_bitfield_unit = true; - } - - fn seen>(&self, item: Id) -> bool { - self.items_seen.contains(&item.into()) - } - - fn set_seen>(&mut self, item: Id) { - self.items_seen.insert(item.into()); - } - - fn seen_function(&self, name: &str) -> bool { - self.functions_seen.contains(name) - } - - fn saw_function(&mut self, name: &str) { - self.functions_seen.insert(name.into()); - } - - /// Get the overload number for the given function name. Increments the - /// counter internally so the next time we ask for the overload for this - /// name, we get the incremented value, and so on. - fn overload_number(&mut self, name: &str) -> u32 { - let counter = self.overload_counters.entry(name.into()).or_insert(0); - let number = *counter; - *counter += 1; - number - } - - fn seen_var(&self, name: &str) -> bool { - self.vars_seen.contains(name) - } - - fn saw_var(&mut self, name: &str) { - self.vars_seen.insert(name.into()); - } - - fn inner(&mut self, cb: F) -> Vec - where - F: FnOnce(&mut Self), - { - let mut new = Self::new(self.codegen_id); - - cb(&mut new); - - self.saw_union |= new.saw_union; - self.saw_incomplete_array |= new.saw_incomplete_array; - self.saw_objc |= new.saw_objc; - self.saw_bitfield_unit |= new.saw_bitfield_unit; - - new.items - } -} - -impl<'a> ops::Deref for CodegenResult<'a> { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.items - } -} - -impl<'a> ops::DerefMut for CodegenResult<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.items - } -} - -/// A trait to convert a rust type into a pointer, optionally const, to the same -/// type. -trait ToPtr { - fn to_ptr(self, is_const: bool) -> quote::Tokens; -} - -impl ToPtr for quote::Tokens { - fn to_ptr(self, is_const: bool) -> quote::Tokens { - if is_const { - quote! { *const #self } - } else { - quote! { *mut #self } - } - } -} - -/// An extension trait for `quote::Tokens` that lets us append any implicit -/// template parameters that exist for some type, if necessary. -trait AppendImplicitTemplateParams { - fn append_implicit_template_params( - &mut self, - ctx: &BindgenContext, - item: &Item, - ); -} - -impl AppendImplicitTemplateParams for quote::Tokens { - fn append_implicit_template_params( - &mut self, - ctx: &BindgenContext, - item: &Item, - ) { - let item = item.id() - .into_resolver() - .through_type_refs() - .resolve(ctx); - - match *item.expect_type().kind() { - TypeKind::UnresolvedTypeRef(..) => { - unreachable!("already resolved unresolved type refs") - } - TypeKind::ResolvedTypeRef(..) => { - unreachable!("we resolved item through type refs") - } - - // None of these types ever have implicit template parameters. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Pointer(..) | - TypeKind::Reference(..) | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Array(..) | - TypeKind::TypeParam | - TypeKind::Opaque | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::BlockPointer | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::TemplateInstantiation(..) => return, - _ => {}, - } - - if let Some(params) = item.used_template_params(ctx) { - if params.is_empty() { - return; - } - - let params = params.into_iter().map(|p| { - p.try_to_rust_ty(ctx, &()) - .expect("template params cannot fail to be a rust type") - }); - - self.append_all(quote! { - < #( #params ),* > - }); - } - } -} - -trait CodeGenerator { - /// Extra information from the caller. - type Extra; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - extra: &Self::Extra, - ); -} - -impl CodeGenerator for Item { - type Extra = (); - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - _extra: &(), - ) { - if !self.is_enabled_for_codegen(ctx) { - return; - } - - if self.is_blacklisted(ctx) || result.seen(self.id()) { - debug!( - "::codegen: Ignoring hidden or seen: \ - self = {:?}", - self - ); - return; - } - - debug!("::codegen: self = {:?}", self); - if !ctx.codegen_items().contains(&self.id()) { - // TODO(emilio, #453): Figure out what to do when this happens - // legitimately, we could track the opaque stuff and disable the - // assertion there I guess. - error!("Found non-whitelisted item in code generation: {:?}", self); - } - - result.set_seen(self.id()); - - match *self.kind() { - ItemKind::Module(ref module) => { - module.codegen(ctx, result, self); - } - ItemKind::Function(ref fun) => { - fun.codegen(ctx, result, self); - } - ItemKind::Var(ref var) => { - var.codegen(ctx, result, self); - } - ItemKind::Type(ref ty) => { - ty.codegen(ctx, result, self); - } - } - } -} - -impl CodeGenerator for Module { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug!("::codegen: item = {:?}", item); - - let codegen_self = |result: &mut CodegenResult, - found_any: &mut bool| { - for child in self.children() { - if ctx.codegen_items().contains(child) { - *found_any = true; - ctx.resolve_item(*child).codegen(ctx, result, &()); - } - } - - if item.id() == ctx.root_module() { - if result.saw_bindgen_union { - utils::prepend_union_types(ctx, &mut *result); - } - if result.saw_incomplete_array { - utils::prepend_incomplete_array_types(ctx, &mut *result); - } - if ctx.need_bindegen_complex_type() { - utils::prepend_complex_type(&mut *result); - } - if result.saw_objc { - utils::prepend_objc_header(ctx, &mut *result); - } - if result.saw_bitfield_unit { - utils::prepend_bitfield_unit_type(&mut *result); - } - } - }; - - if !ctx.options().enable_cxx_namespaces || - (self.is_inline() && - !ctx.options().conservative_inline_namespaces) - { - codegen_self(result, &mut false); - return; - } - - let mut found_any = false; - let inner_items = result.inner(|result| { - result.push(root_import(ctx, item)); - codegen_self(result, &mut found_any); - }); - - // Don't bother creating an empty module. - if !found_any { - return; - } - - let name = item.canonical_name(ctx); - - result.push(if name == "root" { - quote! { - #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] - pub mod root { - #( #inner_items )* - } - } - } else { - let ident = ctx.rust_ident(name); - quote! { - pub mod #ident { - #( #inner_items )* - } - } - }); - } -} - -impl CodeGenerator for Var { - type Extra = Item; - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - use ir::var::VarType; - debug!("::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - let canonical_name = item.canonical_name(ctx); - - if result.seen_var(&canonical_name) { - return; - } - result.saw_var(&canonical_name); - - let canonical_ident = ctx.rust_ident(&canonical_name); - - // We can't generate bindings to static variables of templates. The - // number of actual variables for a single declaration are open ended - // and we don't know what instantiations do or don't exist. - let type_params = item.all_template_params(ctx); - if let Some(params) = type_params { - if !params.is_empty() { - return; - } - } - - let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); - - if let Some(val) = self.val() { - match *val { - VarType::Bool(val) => { - result.push(quote! { - pub const #canonical_ident : #ty = #val ; - }); - } - VarType::Int(val) => { - let int_kind = self.ty() - .into_resolver() - .through_type_aliases() - .through_type_refs() - .resolve(ctx) - .expect_type() - .as_integer() - .unwrap(); - let val = if int_kind.is_signed() { - helpers::ast_ty::int_expr(val) - } else { - helpers::ast_ty::uint_expr(val as _) - }; - result.push(quote! { - pub const #canonical_ident : #ty = #val ; - }); - } - VarType::String(ref bytes) => { - // Account the trailing zero. - // - // TODO: Here we ignore the type we just made up, probably - // we should refactor how the variable type and ty id work. - let len = bytes.len() + 1; - let ty = quote! { - [u8; #len] - }; - - match String::from_utf8(bytes.clone()) { - Ok(string) => { - let cstr = helpers::ast_ty::cstr_expr(string); - result.push(quote! { - pub const #canonical_ident : &'static #ty = #cstr ; - }); - } - Err(..) => { - let bytes = helpers::ast_ty::byte_array_expr(bytes); - result.push(quote! { - pub const #canonical_ident : #ty = #bytes ; - }); - } - } - } - VarType::Float(f) => { - match helpers::ast_ty::float_expr(ctx, f) { - Ok(expr) => result.push(quote! { - pub const #canonical_ident : #ty = #expr ; - }), - Err(..) => return, - } - } - VarType::Char(c) => { - result.push(quote! { - pub const #canonical_ident : #ty = #c ; - }); - } - } - } else { - let mut attrs = vec![]; - if let Some(mangled) = self.mangled_name() { - attrs.push(attributes::link_name(mangled)); - } else if canonical_name != self.name() { - attrs.push(attributes::link_name(self.name())); - } - - let mut tokens = quote!( - extern "C" { - #(#attrs)* - pub static mut #canonical_ident: #ty; - } - ); - - result.push(tokens); - } - } -} - -impl CodeGenerator for Type { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug!("::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - match *self.kind() { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Array(..) | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - TypeKind::Reference(..) | - TypeKind::Function(..) | - TypeKind::ResolvedTypeRef(..) | - TypeKind::Opaque | - TypeKind::TypeParam => { - // These items don't need code generation, they only need to be - // converted to rust types in fields, arguments, and such. - return; - } - TypeKind::TemplateInstantiation(ref inst) => { - inst.codegen(ctx, result, item) - } - TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), - TypeKind::TemplateAlias(inner, _) | - TypeKind::Alias(inner) => { - let inner_item = inner.into_resolver() - .through_type_refs() - .resolve(ctx); - let name = item.canonical_name(ctx); - - { - let through_type_aliases = inner.into_resolver() - .through_type_refs() - .through_type_aliases() - .resolve(ctx); - - // Try to catch the common pattern: - // - // typedef struct foo { ... } foo; - // - // here, and also other more complex cases like #946. - if through_type_aliases.canonical_name(ctx) == name { - return; - } - } - - // If this is a known named type, disallow generating anything - // for it too. - let spelling = self.name().expect("Unnamed alias?"); - if utils::type_from_named(ctx, spelling).is_some() { - return; - } - - let mut outer_params = item.used_template_params(ctx) - .and_then(|ps| if ps.is_empty() { - None - } else { - Some(ps) - }); - - let inner_rust_type = if item.is_opaque(ctx, &()) { - outer_params = None; - self.to_opaque(ctx, item) - } else { - // Its possible that we have better layout information than - // the inner type does, so fall back to an opaque blob based - // on our layout if converting the inner item fails. - let mut inner_ty = inner_item - .try_to_rust_ty_or_opaque(ctx, &()) - .unwrap_or_else(|_| self.to_opaque(ctx, item)); - inner_ty.append_implicit_template_params(ctx, inner_item); - inner_ty - }; - - { - // FIXME(emilio): This is a workaround to avoid generating - // incorrect type aliases because of types that we haven't - // been able to resolve (because, eg, they depend on a - // template parameter). - // - // It's kind of a shame not generating them even when they - // could be referenced, but we already do the same for items - // with invalid template parameters, and at least this way - // they can be replaced, instead of generating plain invalid - // code. - let inner_canon_type = - inner_item.expect_type().canonical_type(ctx); - if inner_canon_type.is_invalid_type_param() { - warn!( - "Item contained invalid named type, skipping: \ - {:?}, {:?}", - item, - inner_item - ); - return; - } - } - - let rust_name = ctx.rust_ident(&name); - - let mut tokens = if let Some(comment) = item.comment(ctx) { - attributes::doc(comment) - } else { - quote! {} - }; - - // We prefer using `pub use` over `pub type` because of: - // https://github.com/rust-lang/rust/issues/26264 - if inner_rust_type.to_string() - .chars() - .all(|c| match c { - // These are the only characters allowed in simple - // paths, eg `good::dogs::Bront`. - 'A'...'Z' | 'a'...'z' | '0'...'9' | ':' | '_' | ' ' => true, - _ => false, - }) && - outer_params.is_none() && - inner_item.expect_type().canonical_type(ctx).is_enum() - { - tokens.append_all(quote! { - pub use - }); - let path = top_level_path(ctx, item); - tokens.append_separated(path, Term::new("::", Span::call_site())); - tokens.append_all(quote! { - :: #inner_rust_type as #rust_name ; - }); - result.push(tokens); - return; - } - - tokens.append_all(quote! { - pub type #rust_name - }); - - if let Some(params) = outer_params { - let params: Vec<_> = params.into_iter() - .filter_map(|p| p.as_template_param(ctx, &())) - .collect(); - if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) { - warn!( - "Item contained invalid template \ - parameter: {:?}", - item - ); - return; - } - - let params = params.iter() - .map(|p| { - p.try_to_rust_ty(ctx, &()) - .expect("type parameters can always convert to rust ty OK") - }); - - tokens.append_all(quote! { - < #( #params ),* > - }); - } - - tokens.append_all(quote! { - = #inner_rust_type ; - }); - - result.push(tokens); - } - TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), - TypeKind::ObjCId | TypeKind::ObjCSel => { - result.saw_objc(); - } - TypeKind::ObjCInterface(ref interface) => { - interface.codegen(ctx, result, item) - } - ref u @ TypeKind::UnresolvedTypeRef(..) => { - unreachable!("Should have been resolved after parsing {:?}!", u) - } - } - } -} - -struct Vtable<'a> { - item_id: ItemId, - #[allow(dead_code)] - methods: &'a [Method], - #[allow(dead_code)] - base_classes: &'a [Base], -} - -impl<'a> Vtable<'a> { - fn new( - item_id: ItemId, - methods: &'a [Method], - base_classes: &'a [Base], - ) -> Self { - Vtable { - item_id: item_id, - methods: methods, - base_classes: base_classes, - } - } -} - -impl<'a> CodeGenerator for Vtable<'a> { - type Extra = Item; - - fn codegen<'b>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'b>, - item: &Item, - ) { - assert_eq!(item.id(), self.item_id); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - // For now, generate an empty struct, later we should generate function - // pointers and whatnot. - let name = ctx.rust_ident(&self.canonical_name(ctx)); - let void = helpers::ast_ty::raw_type(ctx, "c_void"); - result.push(quote! { - #[repr(C)] - pub struct #name ( #void ); - }); - } -} - -impl<'a> ItemCanonicalName for Vtable<'a> { - fn canonical_name(&self, ctx: &BindgenContext) -> String { - format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx)) - } -} - -impl<'a> TryToRustTy for Vtable<'a> { - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - let name = ctx.rust_ident(self.canonical_name(ctx)); - Ok(quote! { - #name - }) - } -} - -impl CodeGenerator for TemplateInstantiation { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug_assert!(item.is_enabled_for_codegen(ctx)); - - // Although uses of instantiations don't need code generation, and are - // just converted to rust types in fields, vars, etc, we take this - // opportunity to generate tests for their layout here. If the - // instantiation is opaque, then its presumably because we don't - // properly understand it (maybe because of specializations), and so we - // shouldn't emit layout tests either. - if !ctx.options().layout_tests || self.is_opaque(ctx, item) { - return; - } - - // If there are any unbound type parameters, then we can't generate a - // layout test because we aren't dealing with a concrete type with a - // concrete size and alignment. - if ctx.uses_any_template_parameters(item.id()) { - return; - } - - let layout = item.kind().expect_type().layout(ctx); - - if let Some(layout) = layout { - let size = layout.size; - let align = layout.align; - - let name = item.full_disambiguated_name(ctx); - let mut fn_name = - format!("__bindgen_test_layout_{}_instantiation", name); - let times_seen = result.overload_number(&fn_name); - if times_seen > 0 { - write!(&mut fn_name, "_{}", times_seen).unwrap(); - } - - let fn_name = ctx.rust_ident_raw(fn_name); - - let prefix = ctx.trait_prefix(); - let ident = item.to_rust_ty_or_opaque(ctx, &()); - let size_of_expr = quote! { - ::#prefix::mem::size_of::<#ident>() - }; - let align_of_expr = quote! { - ::#prefix::mem::align_of::<#ident>() - }; - - let item = quote! { - #[test] - fn #fn_name() { - assert_eq!(#size_of_expr, #size, - concat!("Size of template specialization: ", - stringify!(#ident))); - assert_eq!(#align_of_expr, #align, - concat!("Alignment of template specialization: ", - stringify!(#ident))); - } - }; - - result.push(item); - } - } -} - -/// Trait for implementing the code generation of a struct or union field. -trait FieldCodegen<'a> { - type Extra; - - fn codegen( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - extra: Self::Extra, - ) where - F: Extend, - M: Extend; -} - -impl<'a> FieldCodegen<'a> for Field { - type Extra = (); - - fn codegen( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: (), - ) where - F: Extend, - M: Extend, - { - match *self { - Field::DataMember(ref data) => { - data.codegen( - ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (), - ); - } - Field::Bitfields(ref unit) => { - unit.codegen( - ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (), - ); - } - } - } -} - -impl<'a> FieldCodegen<'a> for FieldData { - type Extra = (); - - fn codegen( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: (), - ) where - F: Extend, - M: Extend, - { - // Bitfields are handled by `FieldCodegen` implementations for - // `BitfieldUnit` and `Bitfield`. - assert!(self.bitfield_width().is_none()); - - let field_item = self.ty().into_resolver().through_type_refs().resolve(ctx); - let field_ty = field_item.expect_type(); - let mut ty = self.ty().to_rust_ty_or_opaque(ctx, &()); - - // NB: If supported, we use proper `union` types. - let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { - if ctx.options().enable_cxx_namespaces { - quote! { - root::__BindgenUnionField<#ty> - } - } else { - quote! { - __BindgenUnionField<#ty> - } - } - } else if let Some(item) = field_ty.is_incomplete_array(ctx) { - result.saw_incomplete_array(); - - let inner = item.to_rust_ty_or_opaque(ctx, &()); - - if ctx.options().enable_cxx_namespaces { - quote! { - root::__IncompleteArrayField<#inner> - } - } else { - quote! { - __IncompleteArrayField<#inner> - } - } - } else { - ty.append_implicit_template_params(ctx, field_item); - ty - }; - - let mut field = quote! {}; - if ctx.options().generate_comments { - if let Some(raw_comment) = self.comment() { - let comment = - comment::preprocess(raw_comment, codegen_depth + 1); - field = attributes::doc(comment); - } - } - - let field_name = - self.name() - .map(|name| ctx.rust_mangle(name).into_owned()) - .expect("Each field should have a name in codegen!"); - let field_ident = ctx.rust_ident_raw(field_name.as_str()); - - if !parent.is_union() { - if let Some(padding_field) = - struct_layout.pad_field(&field_name, field_ty, self.offset()) - { - fields.extend(Some(padding_field)); - } - } - - let is_private = self.annotations().private_fields().unwrap_or( - fields_should_be_private, - ); - - let accessor_kind = - self.annotations().accessor_kind().unwrap_or(accessor_kind); - - if is_private { - field.append_all(quote! { - #field_ident : #ty , - }); - } else { - field.append_all(quote! { - pub #field_ident : #ty , - }); - } - - fields.extend(Some(field)); - - // TODO: Factor the following code out, please! - if accessor_kind == FieldAccessorKind::None { - return; - } - - let getter_name = ctx.rust_ident_raw(format!("get_{}", field_name)); - let mutable_getter_name = - ctx.rust_ident_raw(format!("get_{}_mut", field_name)); - let field_name = ctx.rust_ident_raw(field_name); - - methods.extend(Some(match accessor_kind { - FieldAccessorKind::None => unreachable!(), - FieldAccessorKind::Regular => { - quote! { - #[inline] - pub fn #getter_name(&self) -> & #ty { - &self.#field_name - } - - #[inline] - pub fn #mutable_getter_name(&mut self) -> &mut #ty { - &mut self.#field_name - } - } - } - FieldAccessorKind::Unsafe => { - quote! { - #[inline] - pub unsafe fn #getter_name(&self) -> & #ty { - &self.#field_name - } - - #[inline] - pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty { - &mut self.#field_name - } - } - } - FieldAccessorKind::Immutable => { - quote! { - #[inline] - pub fn #getter_name(&self) -> & #ty { - &self.#field_name - } - } - } - })); - } -} - -impl BitfieldUnit { - /// Get the constructor name for this bitfield unit. - fn ctor_name(&self) -> quote::Tokens { - let ctor_name = Term::new(&format!("new_bitfield_{}", self.nth()), Span::call_site()); - quote! { - #ctor_name - } - } -} - -impl Bitfield { - /// Extend an under construction bitfield unit constructor with this - /// bitfield. This involves two things: - /// - /// 1. Adding a parameter with this bitfield's name and its type. - /// - /// 2. Setting the relevant bits on the `__bindgen_bitfield_unit` variable - /// that's being constructed. - fn extend_ctor_impl( - &self, - ctx: &BindgenContext, - param_name: quote::Tokens, - mut ctor_impl: quote::Tokens, - ) -> quote::Tokens { - let bitfield_ty = ctx.resolve_type(self.ty()); - let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( - "Bitfield without layout? Gah!", - ); - let bitfield_int_ty = helpers::blob(bitfield_ty_layout); - - let offset = self.offset_into_unit(); - let width = self.width() as u8; - let prefix = ctx.trait_prefix(); - - ctor_impl.append_all(quote! { - __bindgen_bitfield_unit.set( - #offset, - #width, - { - let #param_name: #bitfield_int_ty = unsafe { - ::#prefix::mem::transmute(#param_name) - }; - #param_name as u64 - } - ); - }); - - ctor_impl - } -} - -impl<'a> FieldCodegen<'a> for BitfieldUnit { - type Extra = (); - - fn codegen( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: (), - ) where - F: Extend, - M: Extend, - { - result.saw_bitfield_unit(); - - let field_ty = { - let ty = helpers::bitfield_unit(ctx, self.layout()); - if parent.is_union() && !parent.can_be_rust_union(ctx) { - if ctx.options().enable_cxx_namespaces { - quote! { - root::__BindgenUnionField<#ty> - } - } else { - quote! { - __BindgenUnionField<#ty> - } - } - } else { - ty - } - }; - - let unit_field_name = format!("_bitfield_{}", self.nth()); - let unit_field_ident = ctx.rust_ident(&unit_field_name); - - let field = quote! { - pub #unit_field_ident : #field_ty , - }; - fields.extend(Some(field)); - - let unit_field_ty = helpers::bitfield_unit(ctx, self.layout()); - - let ctor_name = self.ctor_name(); - let mut ctor_params = vec![]; - let mut ctor_impl = quote! {}; - let mut generate_ctor = true; - - for bf in self.bitfields() { - // Codegen not allowed for anonymous bitfields - if bf.name().is_none() { - continue; - } - - let mut bitfield_representable_as_int = true; - - bf.codegen( - ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (&unit_field_name, &mut bitfield_representable_as_int), - ); - - // Generating a constructor requires the bitfield to be representable as an integer. - if !bitfield_representable_as_int { - generate_ctor = false; - continue; - } - - let param_name = bitfield_getter_name(ctx, bf); - let bitfield_ty_item = ctx.resolve_item(bf.ty()); - let bitfield_ty = bitfield_ty_item.expect_type(); - let bitfield_ty = - bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); - - ctor_params.push(quote! { - #param_name : #bitfield_ty - }); - ctor_impl = bf.extend_ctor_impl( - ctx, - param_name, - ctor_impl, - ); - } - - if generate_ctor { - methods.extend(Some(quote! { - #[inline] - pub fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty { - let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default(); - #ctor_impl - __bindgen_bitfield_unit - } - })); - } - - struct_layout.saw_bitfield_unit(self.layout()); - } -} - -fn bitfield_getter_name( - ctx: &BindgenContext, - bitfield: &Bitfield, -) -> quote::Tokens { - let name = bitfield.getter_name(); - let name = ctx.rust_ident_raw(name); - quote! { #name } -} - -fn bitfield_setter_name( - ctx: &BindgenContext, - bitfield: &Bitfield, -) -> quote::Tokens { - let setter = bitfield.setter_name(); - let setter = ctx.rust_ident_raw(setter); - quote! { #setter } -} - -impl<'a> FieldCodegen<'a> for Bitfield { - type Extra = (&'a str, &'a mut bool); - - fn codegen( - &self, - ctx: &BindgenContext, - _fields_should_be_private: bool, - _codegen_depth: usize, - _accessor_kind: FieldAccessorKind, - parent: &CompInfo, - _result: &mut CodegenResult, - _struct_layout: &mut StructLayoutTracker, - _fields: &mut F, - methods: &mut M, - (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool), - ) where - F: Extend, - M: Extend, - { - let prefix = ctx.trait_prefix(); - let getter_name = bitfield_getter_name(ctx, self); - let setter_name = bitfield_setter_name(ctx, self); - let unit_field_ident = Term::new(unit_field_name, Span::call_site()); - - let bitfield_ty_item = ctx.resolve_item(self.ty()); - let bitfield_ty = bitfield_ty_item.expect_type(); - - let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( - "Bitfield without layout? Gah!", - ); - let bitfield_int_ty = match helpers::integer_type(bitfield_ty_layout) { - Some(int_ty) => { - *bitfield_representable_as_int = true; - int_ty - } - None => { - *bitfield_representable_as_int = false; - return; - } - }; - - let bitfield_ty = - bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); - - let offset = self.offset_into_unit(); - - let width = self.width() as u8; - - if parent.is_union() && !parent.can_be_rust_union(ctx) { - methods.extend(Some(quote! { - #[inline] - pub fn #getter_name(&self) -> #bitfield_ty { - unsafe { - ::#prefix::mem::transmute( - self.#unit_field_ident.as_ref().get(#offset, #width) - as #bitfield_int_ty - ) - } - } - - #[inline] - pub fn #setter_name(&mut self, val: #bitfield_ty) { - unsafe { - let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); - self.#unit_field_ident.as_mut().set( - #offset, - #width, - val as u64 - ) - } - } - })); - } else { - methods.extend(Some(quote! { - #[inline] - pub fn #getter_name(&self) -> #bitfield_ty { - unsafe { - ::#prefix::mem::transmute( - self.#unit_field_ident.get(#offset, #width) - as #bitfield_int_ty - ) - } - } - - #[inline] - pub fn #setter_name(&mut self, val: #bitfield_ty) { - unsafe { - let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); - self.#unit_field_ident.set( - #offset, - #width, - val as u64 - ) - } - } - })); - } - } -} - -impl CodeGenerator for CompInfo { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug!("::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - // Don't output classes with template parameters that aren't types, and - // also don't output template specializations, neither total or partial. - if self.has_non_type_template_params() { - return; - } - - let used_template_params = item.used_template_params(ctx); - - let ty = item.expect_type(); - let layout = ty.layout(ctx); - let mut packed = self.is_packed(ctx, &layout); - - let canonical_name = item.canonical_name(ctx); - let canonical_ident = ctx.rust_ident(&canonical_name); - - // Generate the vtable from the method list if appropriate. - // - // TODO: I don't know how this could play with virtual methods that are - // not in the list of methods found by us, we'll see. Also, could the - // order of the vtable pointers vary? - // - // FIXME: Once we generate proper vtables, we need to codegen the - // vtable, but *not* generate a field for it in the case that - // HasVtable::has_vtable_ptr is false but HasVtable::has_vtable is true. - // - // Also, we need to generate the vtable in such a way it "inherits" from - // the parent too. - let is_opaque = item.is_opaque(ctx, &()); - let mut fields = vec![]; - let mut struct_layout = - StructLayoutTracker::new(ctx, self, ty, &canonical_name); - - if !is_opaque { - if item.has_vtable_ptr(ctx) { - let vtable = - Vtable::new(item.id(), self.methods(), self.base_members()); - vtable.codegen(ctx, result, item); - - let vtable_type = vtable - .try_to_rust_ty(ctx, &()) - .expect("vtable to Rust type conversion is infallible") - .to_ptr(true); - - fields.push(quote! { - pub vtable_: #vtable_type , - }); - - struct_layout.saw_vtable(); - } - - for base in self.base_members() { - if !base.requires_storage(ctx) { - continue; - } - - let inner = base.ty.to_rust_ty_or_opaque(ctx, &()); - let field_name = ctx.rust_ident(&base.field_name); - - let base_ty = ctx.resolve_type(base.ty); - struct_layout.saw_base(base_ty); - - fields.push(quote! { - pub #field_name : #inner , - }); - } - } - - let mut methods = vec![]; - if !is_opaque { - let codegen_depth = item.codegen_depth(ctx); - let fields_should_be_private = - item.annotations().private_fields().unwrap_or(false); - let struct_accessor_kind = item.annotations() - .accessor_kind() - .unwrap_or(FieldAccessorKind::None); - for field in self.fields() { - field.codegen( - ctx, - fields_should_be_private, - codegen_depth, - struct_accessor_kind, - self, - result, - &mut struct_layout, - &mut fields, - &mut methods, - (), - ); - } - } - - let is_union = self.kind() == CompKind::Union; - let layout = item.kind().expect_type().layout(ctx); - if is_union && !is_opaque && !self.is_forward_declaration() { - result.saw_union(); - if !self.can_be_rust_union(ctx) { - result.saw_bindgen_union(); - } - - let layout = layout.expect("Unable to get layout information?"); - let ty = helpers::blob(layout); - - fields.push(if self.can_be_rust_union(ctx) { - quote! { - _bindgen_union_align: #ty , - } - } else { - struct_layout.saw_union(layout); - - quote! { - pub bindgen_union_field: #ty , - } - }); - } - - let mut explicit_align = None; - if is_opaque { - // Opaque item should not have generated methods, fields. - debug_assert!(fields.is_empty()); - debug_assert!(methods.is_empty()); - - match layout { - Some(l) => { - explicit_align = Some(l.align); - - let ty = helpers::blob(l); - fields.push(quote! { - pub _bindgen_opaque_blob: #ty , - }); - } - None => { - warn!("Opaque type without layout! Expect dragons!"); - } - } - } else if !is_union && !item.is_zero_sized(ctx) { - if let Some(padding_field) = - layout.and_then(|layout| struct_layout.pad_struct(layout)) - { - fields.push(padding_field); - } - - if let Some(layout) = layout { - if struct_layout.requires_explicit_align(layout) { - if layout.align == 1 { - packed = true; - } else { - explicit_align = Some(layout.align); - let ty = helpers::blob(Layout::new(0, layout.align)); - fields.push(quote! { - pub __bindgen_align: #ty , - }); - } - } - } - } - - // C++ requires every struct to be addressable, so what C++ compilers do - // is making the struct 1-byte sized. - // - // This is apparently not the case for C, see: - // https://github.com/rust-lang-nursery/rust-bindgen/issues/551 - // - // Just get the layout, and assume C++ if not. - // - // NOTE: This check is conveniently here to avoid the dummy fields we - // may add for unused template parameters. - if self.is_forward_declaration() { - fields.push(quote! { - _unused: [u8; 0], - }); - } else if item.is_zero_sized(ctx) { - let has_address = if is_opaque { - // Generate the address field if it's an opaque type and - // couldn't determine the layout of the blob. - layout.is_none() - } else { - layout.map_or(true, |l| l.size != 0) - }; - - if has_address { - let ty = helpers::blob(Layout::new(1, 1)); - fields.push(quote! { - pub _address: #ty, - }); - } - } - - let mut generic_param_names = vec![]; - - if let Some(ref params) = used_template_params { - for (idx, ty) in params.iter().enumerate() { - let param = ctx.resolve_type(*ty); - let name = param.name().unwrap(); - let ident = ctx.rust_ident(name); - generic_param_names.push(ident.clone()); - - let prefix = ctx.trait_prefix(); - let field_name = ctx.rust_ident(format!("_phantom_{}", idx)); - fields.push(quote! { - pub #field_name : ::#prefix::marker::PhantomData< - ::#prefix::cell::UnsafeCell<#ident> - > , - }); - } - } - - let generics = if !generic_param_names.is_empty() { - let generic_param_names = generic_param_names.clone(); - quote! { - < #( #generic_param_names ),* > - } - } else { - quote! { } - }; - - let mut attributes = vec![]; - let mut needs_clone_impl = false; - let mut needs_default_impl = false; - let mut needs_debug_impl = false; - let mut needs_partialeq_impl = false; - if let Some(comment) = item.comment(ctx) { - attributes.push(attributes::doc(comment)); - } - if packed && !is_opaque { - attributes.push(attributes::repr_list(&["C", "packed"])); - } else { - attributes.push(attributes::repr("C")); - } - - if ctx.options().rust_features().repr_align { - if let Some(explicit) = explicit_align { - // Ensure that the struct has the correct alignment even in - // presence of alignas. - let explicit = helpers::ast_ty::int_expr(explicit as i64); - attributes.push(quote! { - #[repr(align(#explicit))] - }); - } - } - - - let mut derives = vec![]; - if item.can_derive_debug(ctx) { - derives.push("Debug"); - } else { - needs_debug_impl = ctx.options().derive_debug && - ctx.options().impl_debug - } - - if item.can_derive_default(ctx) { - derives.push("Default"); - } else { - needs_default_impl = - ctx.options().derive_default && !self.is_forward_declaration(); - } - - if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { - derives.push("Copy"); - - if ctx.options().rust_features().builtin_clone_impls || - used_template_params.is_some() - { - // FIXME: This requires extra logic if you have a big array in a - // templated struct. The reason for this is that the magic: - // fn clone(&self) -> Self { *self } - // doesn't work for templates. - // - // It's not hard to fix though. - derives.push("Clone"); - } else { - needs_clone_impl = true; - } - } - - if item.can_derive_hash(ctx) { - derives.push("Hash"); - } - - if item.can_derive_partialord(ctx) { - derives.push("PartialOrd"); - } - - if item.can_derive_ord(ctx) { - derives.push("Ord"); - } - - if item.can_derive_partialeq(ctx) { - derives.push("PartialEq"); - } else { - needs_partialeq_impl = - ctx.options().derive_partialeq && - ctx.options().impl_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(item.id()) == CanDerive::ArrayTooLarge; - } - - if item.can_derive_eq(ctx) { - derives.push("Eq"); - } - - if !derives.is_empty() { - attributes.push(attributes::derives(&derives)) - } - - let mut tokens = if is_union && self.can_be_rust_union(ctx) { - quote! { - #( #attributes )* - pub union #canonical_ident - } - } else { - quote! { - #( #attributes )* - pub struct #canonical_ident - } - }; - - tokens.append_all(quote! { - #generics { - #( #fields )* - } - }); - result.push(tokens); - - // Generate the inner types and all that stuff. - // - // TODO: In the future we might want to be smart, and use nested - // modules, and whatnot. - for ty in self.inner_types() { - let child_item = ctx.resolve_item(*ty); - // assert_eq!(child_item.parent_id(), item.id()); - child_item.codegen(ctx, result, &()); - } - - // NOTE: Some unexposed attributes (like alignment attributes) may - // affect layout, so we're bad and pray to the gods for avoid sending - // all the tests to shit when parsing things like max_align_t. - if self.found_unknown_attr() { - warn!( - "Type {} has an unkown attribute that may affect layout", - canonical_ident.as_str() - ); - } - - if used_template_params.is_none() { - if !is_opaque { - for var in self.inner_vars() { - ctx.resolve_item(*var).codegen(ctx, result, &()); - } - } - - if ctx.options().layout_tests && !self.is_forward_declaration() { - if let Some(layout) = layout { - let fn_name = - format!("bindgen_test_layout_{}", canonical_ident.as_str()); - let fn_name = ctx.rust_ident_raw(fn_name); - let prefix = ctx.trait_prefix(); - let size_of_expr = quote! { - ::#prefix::mem::size_of::<#canonical_ident>() - }; - let align_of_expr = quote! { - ::#prefix::mem::align_of::<#canonical_ident>() - }; - let size = layout.size; - let align = layout.align; - - let check_struct_align = - if align > ctx.target_pointer_size() && - !ctx.options().rust_features().repr_align - { - None - } else { - Some(quote! { - assert_eq!(#align_of_expr, - #align, - concat!("Alignment of ", stringify!(#canonical_ident))); - - }) - }; - - // FIXME when [issue #465](https://github.com/rust-lang-nursery/rust-bindgen/issues/465) ready - let too_many_base_vtables = self.base_members() - .iter() - .filter(|base| base.ty.has_vtable(ctx)) - .count() > 1; - - let should_skip_field_offset_checks = is_opaque || - too_many_base_vtables; - - let check_field_offset = - if should_skip_field_offset_checks { - vec![] - } else { - let asserts = self.fields() - .iter() - .filter_map(|field| match *field { - Field::DataMember(ref f) if f.name().is_some() => Some(f), - _ => None, - }) - .flat_map(|field| { - let name = field.name().unwrap(); - field.offset().and_then(|offset| { - let field_offset = offset / 8; - let field_name = ctx.rust_ident(name); - - Some(quote! { - assert_eq!( - unsafe { - &(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize - }, - #field_offset, - concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name)) - ); - }) - }) - }) - .collect::>(); - - asserts - }; - - let item = quote! { - #[test] - fn #fn_name() { - assert_eq!(#size_of_expr, - #size, - concat!("Size of: ", stringify!(#canonical_ident))); - - #check_struct_align - #( #check_field_offset )* - } - }; - result.push(item); - } - } - - let mut method_names = Default::default(); - if ctx.options().codegen_config.methods { - for method in self.methods() { - assert!(method.kind() != MethodKind::Constructor); - method.codegen_method( - ctx, - &mut methods, - &mut method_names, - result, - self, - ); - } - } - - if ctx.options().codegen_config.constructors { - for sig in self.constructors() { - Method::new( - MethodKind::Constructor, - *sig, - /* const */ - false, - ).codegen_method( - ctx, - &mut methods, - &mut method_names, - result, - self, - ); - } - } - - if ctx.options().codegen_config.destructors { - if let Some((kind, destructor)) = self.destructor() { - debug_assert!(kind.is_destructor()); - Method::new(kind, destructor, false).codegen_method( - ctx, - &mut methods, - &mut method_names, - result, - self, - ); - } - } - } - - // NB: We can't use to_rust_ty here since for opaque types this tries to - // use the specialization knowledge to generate a blob field. - let ty_for_impl = quote! { - #canonical_ident #generics - }; - - if needs_clone_impl { - result.push(quote! { - impl #generics Clone for #ty_for_impl { - fn clone(&self) -> Self { *self } - } - }); - } - - if needs_default_impl { - let prefix = ctx.trait_prefix(); - result.push(quote! { - impl #generics Default for #ty_for_impl { - fn default() -> Self { unsafe { ::#prefix::mem::zeroed() } } - } - }); - } - - if needs_debug_impl { - let impl_ = impl_debug::gen_debug_impl( - ctx, - self.fields(), - item, - self.kind(), - ); - - result.push(quote! { - impl #generics ::std::fmt::Debug for #ty_for_impl { - #impl_ - } - }); - } - - if needs_partialeq_impl { - if let Some(impl_) = impl_partialeq::gen_partialeq_impl(ctx, self, item, &ty_for_impl) { - - let partialeq_bounds = if !generic_param_names.is_empty() { - let bounds = generic_param_names.iter().map(|t| { - quote! { #t: PartialEq } - }); - quote! { where #( #bounds ),* } - } else { - quote! { } - }; - - let prefix = ctx.trait_prefix(); - result.push(quote! { - impl #generics ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds { - #impl_ - } - }); - } - } - - if !methods.is_empty() { - result.push(quote! { - impl #generics #ty_for_impl { - #( #methods )* - } - }); - } - } -} - -trait MethodCodegen { - fn codegen_method<'a>( - &self, - ctx: &BindgenContext, - methods: &mut Vec, - method_names: &mut HashMap, - result: &mut CodegenResult<'a>, - parent: &CompInfo, - ); -} - -impl MethodCodegen for Method { - fn codegen_method<'a>( - &self, - ctx: &BindgenContext, - methods: &mut Vec, - method_names: &mut HashMap, - result: &mut CodegenResult<'a>, - _parent: &CompInfo, - ) { - assert!({ - let cc = &ctx.options().codegen_config; - match self.kind() { - MethodKind::Constructor => cc.constructors, - MethodKind::Destructor => cc.destructors, - MethodKind::VirtualDestructor { .. } => cc.destructors, - MethodKind::Static | MethodKind::Normal | - MethodKind::Virtual { .. } => cc.methods, - } - }); - - // TODO(emilio): We could generate final stuff at least. - if self.is_virtual() { - return; // FIXME - } - - // First of all, output the actual function. - let function_item = ctx.resolve_item(self.signature()); - function_item.codegen(ctx, result, &()); - - let function = function_item.expect_function(); - let signature_item = ctx.resolve_item(function.signature()); - let mut name = match self.kind() { - MethodKind::Constructor => "new".into(), - MethodKind::Destructor => "destruct".into(), - _ => function.name().to_owned(), - }; - - let signature = match *signature_item.expect_type().kind() { - TypeKind::Function(ref sig) => sig, - _ => panic!("How in the world?"), - }; - - if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi) { - return; - } - - // Do not generate variadic methods, since rust does not allow - // implementing them, and we don't do a good job at it anyway. - if signature.is_variadic() { - return; - } - - let count = { - let count = method_names.entry(name.clone()).or_insert(0); - *count += 1; - *count - 1 - }; - - if count != 0 { - name.push_str(&count.to_string()); - } - - let function_name = ctx.rust_ident(function_item.canonical_name(ctx)); - let mut args = utils::fnsig_arguments(ctx, signature); - let mut ret = utils::fnsig_return_ty(ctx, signature); - - if !self.is_static() && !self.is_constructor() { - args[0] = if self.is_const() { - quote! { &self } - } else { - quote! { &mut self } - }; - } - - // If it's a constructor, we always return `Self`, and we inject the - // "this" parameter, so there's no need to ask the user for it. - // - // Note that constructors in Clang are represented as functions with - // return-type = void. - if self.is_constructor() { - args.remove(0); - ret = quote! { -> Self }; - } - - let mut exprs = - helpers::ast_ty::arguments_from_signature(&signature, ctx); - - let mut stmts = vec![]; - - // If it's a constructor, we need to insert an extra parameter with a - // variable called `__bindgen_tmp` we're going to create. - if self.is_constructor() { - let prefix = ctx.trait_prefix(); - let tmp_variable_decl = - quote! { - let mut __bindgen_tmp = ::#prefix::mem::uninitialized() - }; - stmts.push(tmp_variable_decl); - exprs[0] = quote! { - &mut __bindgen_tmp - }; - } else if !self.is_static() { - assert!(!exprs.is_empty()); - exprs[0] = quote! { - self - }; - }; - - let call = quote! { - #function_name (#( #exprs ),* ) - }; - - stmts.push(call); - - if self.is_constructor() { - stmts.push(quote! { - __bindgen_tmp - }); - } - - let block = quote! { - #( #stmts );* - }; - - let mut attrs = vec![]; - attrs.push(attributes::inline()); - - let name = ctx.rust_ident(&name); - methods.push(quote! { - #[inline] - pub unsafe fn #name ( #( #args ),* ) #ret { - #block - } - }); - } -} - -/// A helper type that represents different enum variations. -#[derive(Copy, Clone)] -enum EnumVariation { - Rust, - Bitfield, - Consts, - ModuleConsts -} - -impl EnumVariation { - fn is_rust(&self) -> bool { - match *self { - EnumVariation::Rust => true, - _ => false - } - } - - fn is_bitfield(&self) -> bool { - match *self { - EnumVariation::Bitfield {..} => true, - _ => false - } - } - - /// Both the `Const` and `ModuleConsts` variants will cause this to return - /// true. - fn is_const(&self) -> bool { - match *self { - EnumVariation::Consts | EnumVariation::ModuleConsts => true, - _ => false - } - } -} - -/// A helper type to construct different enum variations. -enum EnumBuilder<'a> { - Rust { - codegen_depth: usize, - attrs: Vec, - ident: Term, - tokens: quote::Tokens, - emitted_any_variants: bool, - }, - Bitfield { - codegen_depth: usize, - canonical_name: &'a str, - tokens: quote::Tokens, - }, - Consts { - variants: Vec, - codegen_depth: usize, - }, - ModuleConsts { - codegen_depth: usize, - module_name: &'a str, - module_items: Vec, - }, -} - -impl<'a> EnumBuilder<'a> { - /// Returns the depth of the code generation for a variant of this enum. - fn codegen_depth(&self) -> usize { - match *self { - EnumBuilder::Rust { codegen_depth, .. } | - EnumBuilder::Bitfield { codegen_depth, .. } | - EnumBuilder::ModuleConsts { codegen_depth, .. } | - EnumBuilder::Consts { codegen_depth, .. } => codegen_depth, - } - } - - /// Create a new enum given an item builder, a canonical name, a name for - /// the representation, and which variation it should be generated as. - fn new( - name: &'a str, - attrs: Vec, - repr: quote::Tokens, - enum_variation: EnumVariation, - enum_codegen_depth: usize, - ) -> Self { - let ident = Term::new(name, Span::call_site()); - - match enum_variation { - EnumVariation::Bitfield => { - EnumBuilder::Bitfield { - codegen_depth: enum_codegen_depth, - canonical_name: name, - tokens: quote! { - #( #attrs )* - pub struct #ident (pub #repr); - }, - } - } - - EnumVariation::Rust => { - let tokens = quote!(); - EnumBuilder::Rust { - codegen_depth: enum_codegen_depth + 1, - attrs, - ident, - tokens, - emitted_any_variants: false, - } - } - - EnumVariation::Consts => { - EnumBuilder::Consts { - variants: vec![ - quote! { - #( #attrs )* - pub type #ident = #repr; - } - ], - codegen_depth: enum_codegen_depth, - } - } - - EnumVariation::ModuleConsts => { - let ident = Term::new(CONSTIFIED_ENUM_MODULE_REPR_NAME, Span::call_site()); - let type_definition = quote! { - #( #attrs )* - pub type #ident = #repr; - }; - - EnumBuilder::ModuleConsts { - codegen_depth: enum_codegen_depth + 1, - module_name: name, - module_items: vec![type_definition], - } - } - } - } - - /// Add a variant to this enum. - fn with_variant<'b>( - self, - ctx: &BindgenContext, - variant: &EnumVariant, - mangling_prefix: Option<&str>, - rust_ty: quote::Tokens, - result: &mut CodegenResult<'b>, - is_ty_named: bool, - ) -> Self { - let variant_name = ctx.rust_mangle(variant.name()); - let expr = match variant.val() { - EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), - EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v), - }; - - let mut doc = quote! {}; - if ctx.options().generate_comments { - if let Some(raw_comment) = variant.comment() { - let comment = comment::preprocess(raw_comment, self.codegen_depth()); - doc = attributes::doc(comment); - } - } - - match self { - EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants: _, codegen_depth } => { - let name = ctx.rust_ident(variant_name); - EnumBuilder::Rust { - attrs, - ident, - codegen_depth, - tokens: quote! { - #tokens - #doc - #name = #expr, - }, - emitted_any_variants: true, - } - } - - EnumBuilder::Bitfield { canonical_name, .. } => { - if ctx.options().rust_features().associated_const && is_ty_named { - let enum_ident = ctx.rust_ident(canonical_name); - let variant_ident = ctx.rust_ident(variant_name); - result.push(quote! { - impl #enum_ident { - #doc - pub const #variant_ident : #rust_ty = #rust_ty ( #expr ); - } - }); - } else { - let ident = ctx.rust_ident(match mangling_prefix { - Some(prefix) => { - Cow::Owned(format!("{}_{}", prefix, variant_name)) - } - None => variant_name, - }); - result.push(quote! { - #doc - pub const #ident : #rust_ty = #rust_ty ( #expr ); - }); - } - - self - } - - EnumBuilder::Consts { - .. - } => { - let constant_name = match mangling_prefix { - Some(prefix) => { - Cow::Owned(format!("{}_{}", prefix, variant_name)) - } - None => variant_name, - }; - - let ident = ctx.rust_ident(constant_name); - result.push(quote! { - #doc - pub const #ident : #rust_ty = #expr ; - }); - - self - } - EnumBuilder::ModuleConsts { - codegen_depth, - module_name, - mut module_items, - } => { - let name = ctx.rust_ident(variant_name); - let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME); - module_items.push(quote! { - #doc - pub const #name : #ty = #expr ; - }); - - EnumBuilder::ModuleConsts { - module_name, - module_items, - codegen_depth, - } - } - } - } - - fn build<'b>( - self, - ctx: &BindgenContext, - rust_ty: quote::Tokens, - result: &mut CodegenResult<'b>, - ) -> quote::Tokens { - match self { - EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants, .. } => { - let variants = if !emitted_any_variants { - quote!(__bindgen_cannot_repr_c_on_empty_enum = 0) - } else { - tokens - }; - - quote! { - #( #attrs )* - pub enum #ident { - #variants - } - } - } - EnumBuilder::Bitfield { - canonical_name, - tokens, - .. - } => { - let rust_ty_name = ctx.rust_ident_raw(canonical_name); - let prefix = ctx.trait_prefix(); - - result.push(quote! { - impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty { - type Output = Self; - - #[inline] - fn bitor(self, other: Self) -> Self { - #rust_ty_name(self.0 | other.0) - } - } - }); - - result.push(quote! { - impl ::#prefix::ops::BitOrAssign for #rust_ty { - #[inline] - fn bitor_assign(&mut self, rhs: #rust_ty) { - self.0 |= rhs.0; - } - } - }); - - result.push(quote! { - impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty { - type Output = Self; - - #[inline] - fn bitand(self, other: Self) -> Self { - #rust_ty_name(self.0 & other.0) - } - } - }); - - result.push(quote! { - impl ::#prefix::ops::BitAndAssign for #rust_ty { - #[inline] - fn bitand_assign(&mut self, rhs: #rust_ty) { - self.0 &= rhs.0; - } - } - }); - - tokens - } - EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* }, - EnumBuilder::ModuleConsts { - module_items, - module_name, - .. - } => { - let ident = ctx.rust_ident(module_name); - quote! { - pub mod #ident { - #( #module_items )* - } - } - } - } - } -} - -impl CodeGenerator for Enum { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug!("::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - let name = item.canonical_name(ctx); - let ident = ctx.rust_ident(&name); - let enum_ty = item.expect_type(); - let layout = enum_ty.layout(ctx); - - let repr = self.repr().map(|repr| ctx.resolve_type(repr)); - let repr = match repr { - Some(repr) => { - match *repr.canonical_type(ctx).kind() { - TypeKind::Int(int_kind) => int_kind, - _ => panic!("Unexpected type as enum repr"), - } - } - None => { - warn!( - "Guessing type of enum! Forward declarations of enums \ - shouldn't be legal!" - ); - IntKind::Int - } - }; - - let signed = repr.is_signed(); - let size = layout - .map(|l| l.size) - .or_else(|| repr.known_size()) - .unwrap_or(0); - - let repr_name = match (signed, size) { - (true, 1) => "i8", - (false, 1) => "u8", - (true, 2) => "i16", - (false, 2) => "u16", - (true, 4) => "i32", - (false, 4) => "u32", - (true, 8) => "i64", - (false, 8) => "u64", - _ => { - warn!("invalid enum decl: signed: {}, size: {}", signed, size); - "i32" - } - }; - - // ModuleConsts has higher precedence before Rust in order to avoid problems with - // overlapping match patterns - let variation = if self.is_constified_enum_module(ctx, item) { - EnumVariation::ModuleConsts - } else if self.is_bitfield(ctx, item) { - EnumVariation::Bitfield - } else if self.is_rustified_enum(ctx, item) { - EnumVariation::Rust - } else { - // We generate consts by default - EnumVariation::Consts - }; - - let mut attrs = vec![]; - - // TODO(emilio): Delegate this to the builders? - if variation.is_rust() { - attrs.push(attributes::repr(repr_name)); - } else if variation.is_bitfield() { - attrs.push(attributes::repr("C")); - } - - if let Some(comment) = item.comment(ctx) { - attrs.push(attributes::doc(comment)); - } - - if !variation.is_const() { - attrs.push(attributes::derives( - &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"], - )); - } - - fn add_constant<'a>( - ctx: &BindgenContext, - enum_: &Type, - // Only to avoid recomputing every time. - enum_canonical_name: &Term, - // May be the same as "variant" if it's because the - // enum is unnamed and we still haven't seen the - // value. - variant_name: &str, - referenced_name: &Term, - enum_rust_ty: quote::Tokens, - result: &mut CodegenResult<'a>, - ) { - let constant_name = if enum_.name().is_some() { - if ctx.options().prepend_enum_name { - format!("{}_{}", enum_canonical_name.as_str(), variant_name) - } else { - variant_name.into() - } - } else { - variant_name.into() - }; - let constant_name = ctx.rust_ident(constant_name); - - result.push(quote! { - pub const #constant_name : #enum_rust_ty = - #enum_canonical_name :: #referenced_name ; - }); - } - - let repr = { - let repr_name = ctx.rust_ident_raw(repr_name); - quote! { #repr_name } - }; - - let mut builder = EnumBuilder::new( - &name, - attrs, - repr, - variation, - item.codegen_depth(ctx), - ); - - // A map where we keep a value -> variant relation. - let mut seen_values = HashMap::<_, Term>::new(); - let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &()); - let is_toplevel = item.is_toplevel(ctx); - - // Used to mangle the constants we generate in the unnamed-enum case. - let parent_canonical_name = if is_toplevel { - None - } else { - Some(item.parent_id().canonical_name(ctx)) - }; - - let constant_mangling_prefix = if ctx.options().prepend_enum_name { - if enum_ty.name().is_none() { - parent_canonical_name.as_ref().map(|n| &**n) - } else { - Some(&*name) - } - } else { - None - }; - - // NB: We defer the creation of constified variants, in case we find - // another variant with the same value (which is the common thing to - // do). - let mut constified_variants = VecDeque::new(); - - let mut iter = self.variants().iter().peekable(); - while let Some(variant) = iter.next().or_else(|| { - constified_variants.pop_front() - }) { - if variant.hidden() { - continue; - } - - if variant.force_constification() && iter.peek().is_some() { - constified_variants.push_back(variant); - continue; - } - - match seen_values.entry(variant.val()) { - Entry::Occupied(ref entry) => { - if variation.is_rust() { - let variant_name = ctx.rust_mangle(variant.name()); - let mangled_name = - if is_toplevel || enum_ty.name().is_some() { - variant_name - } else { - let parent_name = - parent_canonical_name.as_ref().unwrap(); - - Cow::Owned( - format!("{}_{}", parent_name, variant_name), - ) - }; - - let existing_variant_name = entry.get(); - add_constant( - ctx, - enum_ty, - &ident, - &*mangled_name, - existing_variant_name, - enum_rust_ty.clone(), - result, - ); - } else { - builder = builder.with_variant( - ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result, - enum_ty.name().is_some(), - ); - } - } - Entry::Vacant(entry) => { - builder = builder.with_variant( - ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result, - enum_ty.name().is_some(), - ); - - let variant_name = ctx.rust_ident(variant.name()); - - // If it's an unnamed enum, or constification is enforced, - // we also generate a constant so it can be properly - // accessed. - if (variation.is_rust() && enum_ty.name().is_none()) || - variant.force_constification() - { - let mangled_name = if is_toplevel { - variant_name.clone() - } else { - let parent_name = - parent_canonical_name.as_ref().unwrap(); - - Term::new( - &format!( - "{}_{}", - parent_name, - variant_name.as_str() - ), - Span::call_site() - ) - }; - - add_constant( - ctx, - enum_ty, - &ident, - mangled_name.as_str(), - &variant_name, - enum_rust_ty.clone(), - result, - ); - } - - entry.insert(variant_name); - } - } - } - - let item = builder.build(ctx, enum_rust_ty, result); - result.push(item); - } -} - -/// Fallible conversion to an opaque blob. -/// -/// Implementors of this trait should provide the `try_get_layout` method to -/// fallibly get this thing's layout, which the provided `try_to_opaque` trait -/// method will use to convert the `Layout` into an opaque blob Rust type. -trait TryToOpaque { - type Extra; - - /// Get the layout for this thing, if one is available. - fn try_get_layout( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> error::Result; - - /// Do not override this provided trait method. - fn try_to_opaque( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> error::Result { - self.try_get_layout(ctx, extra).map(|layout| { - helpers::blob(layout) - }) - } -} - -/// Infallible conversion of an IR thing to an opaque blob. -/// -/// The resulting layout is best effort, and is unfortunately not guaranteed to -/// be correct. When all else fails, we fall back to a single byte layout as a -/// last resort, because C++ does not permit zero-sized types. See the note in -/// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits -/// and when each is appropriate. -/// -/// Don't implement this directly. Instead implement `TryToOpaque`, and then -/// leverage the blanket impl for this trait. -trait ToOpaque: TryToOpaque { - fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout { - self.try_get_layout(ctx, extra) - .unwrap_or_else(|_| Layout::for_size(ctx, 1)) - } - - fn to_opaque( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> quote::Tokens { - let layout = self.get_layout(ctx, extra); - helpers::blob(layout) - } -} - -impl ToOpaque for T -where - T: TryToOpaque, -{ -} - -/// Fallible conversion from an IR thing to an *equivalent* Rust type. -/// -/// If the C/C++ construct represented by the IR thing cannot (currently) be -/// represented in Rust (for example, instantiations of templates with -/// const-value generic parameters) then the impl should return an `Err`. It -/// should *not* attempt to return an opaque blob with the correct size and -/// alignment. That is the responsibility of the `TryToOpaque` trait. -trait TryToRustTy { - type Extra; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> error::Result; -} - -/// Fallible conversion to a Rust type or an opaque blob with the correct size -/// and alignment. -/// -/// Don't implement this directly. Instead implement `TryToRustTy` and -/// `TryToOpaque`, and then leverage the blanket impl for this trait below. -trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { - type Extra; - - fn try_to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &::Extra, - ) -> error::Result; -} - -impl TryToRustTyOrOpaque for T -where - T: TryToRustTy - + TryToOpaque, -{ - type Extra = E; - - fn try_to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &E, - ) -> error::Result { - self.try_to_rust_ty(ctx, extra).or_else( - |_| if let Ok(layout) = - self.try_get_layout(ctx, extra) - { - Ok(helpers::blob(layout)) - } else { - Err(error::Error::NoLayoutForOpaqueBlob) - }, - ) - } -} - -/// Infallible conversion to a Rust type, or an opaque blob with a best effort -/// of correct size and alignment. -/// -/// Don't implement this directly. Instead implement `TryToRustTy` and -/// `TryToOpaque`, and then leverage the blanket impl for this trait below. -/// -/// ### Fallible vs. Infallible Conversions to Rust Types -/// -/// When should one use this infallible `ToRustTyOrOpaque` trait versus the -/// fallible `TryTo{RustTy, Opaque, RustTyOrOpaque}` triats? All fallible trait -/// implementations that need to convert another thing into a Rust type or -/// opaque blob in a nested manner should also use fallible trait methods and -/// propagate failure up the stack. Only infallible functions and methods like -/// CodeGenerator implementations should use the infallible -/// `ToRustTyOrOpaque`. The further out we push error recovery, the more likely -/// we are to get a usable `Layout` even if we can't generate an equivalent Rust -/// type for a C++ construct. -trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { - type Extra; - - fn to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &::Extra, - ) -> quote::Tokens; -} - -impl ToRustTyOrOpaque for T -where - T: TryToRustTy + ToOpaque, -{ - type Extra = E; - - fn to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &E, - ) -> quote::Tokens { - self.try_to_rust_ty(ctx, extra).unwrap_or_else(|_| { - self.to_opaque(ctx, extra) - }) - } -} - -impl TryToOpaque for T -where - T: Copy + Into -{ - type Extra = (); - - fn try_get_layout( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - ctx.resolve_item((*self).into()).try_get_layout(ctx, &()) - } -} - -impl TryToRustTy for T -where - T: Copy + Into -{ - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &()) - } -} - -impl TryToOpaque for Item { - type Extra = (); - - fn try_get_layout( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - self.kind().expect_type().try_get_layout(ctx, self) - } -} - -impl TryToRustTy for Item { - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - self.kind().expect_type().try_to_rust_ty(ctx, self) - } -} - -impl TryToOpaque for Type { - type Extra = Item; - - fn try_get_layout( - &self, - ctx: &BindgenContext, - _: &Item, - ) -> error::Result { - self.layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob) - } -} - -impl TryToRustTy for Type { - type Extra = Item; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> error::Result { - use self::helpers::ast_ty::*; - - match *self.kind() { - TypeKind::Void => Ok(raw_type(ctx, "c_void")), - // TODO: we should do something smart with nullptr, or maybe *const - // c_void is enough? - TypeKind::NullPtr => { - Ok(raw_type(ctx, "c_void").to_ptr(true)) - } - TypeKind::Int(ik) => { - match ik { - IntKind::Bool => Ok(quote! { bool }), - IntKind::Char { - .. - } => Ok(raw_type(ctx, "c_char")), - IntKind::SChar => Ok(raw_type(ctx, "c_schar")), - IntKind::UChar => Ok(raw_type(ctx, "c_uchar")), - IntKind::Short => Ok(raw_type(ctx, "c_short")), - IntKind::UShort => Ok(raw_type(ctx, "c_ushort")), - IntKind::Int => Ok(raw_type(ctx, "c_int")), - IntKind::UInt => Ok(raw_type(ctx, "c_uint")), - IntKind::Long => Ok(raw_type(ctx, "c_long")), - IntKind::ULong => Ok(raw_type(ctx, "c_ulong")), - IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")), - IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")), - - IntKind::I8 => Ok(quote! { i8 }), - IntKind::U8 => Ok(quote! { u8 }), - IntKind::I16 => Ok(quote! { i16 }), - IntKind::U16 => Ok(quote! { u16 }), - IntKind::I32 => Ok(quote! { i32 }), - IntKind::U32 => Ok(quote! { u32 }), - IntKind::I64 => Ok(quote! { i64 }), - IntKind::U64 => Ok(quote! { u64 }), - IntKind::Custom { - name, .. - } => { - let ident = ctx.rust_ident_raw(name); - Ok(quote! { - #ident - }) - } - // FIXME: This doesn't generate the proper alignment, but we - // can't do better right now. We should be able to use - // i128/u128 when they're available. - IntKind::U128 | IntKind::I128 => { - Ok(quote! { [u64; 2] }) - } - } - } - TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)), - TypeKind::Complex(fk) => { - let float_path = float_kind_rust_type(ctx, fk); - - ctx.generated_bindegen_complex(); - Ok(if ctx.options().enable_cxx_namespaces { - quote! { - root::__BindgenComplex<#float_path> - } - } else { - quote! { - __BindgenComplex<#float_path> - } - }) - } - TypeKind::Function(ref fs) => { - // We can't rely on the sizeof(Option>) == - // sizeof(NonZero<_>) optimization with opaque blobs (because - // they aren't NonZero), so don't *ever* use an or_opaque - // variant here. - let ty = fs.try_to_rust_ty(ctx, &())?; - - let prefix = ctx.trait_prefix(); - Ok(quote! { - ::#prefix::option::Option<#ty> - }) - } - TypeKind::Array(item, len) => { - let ty = item.try_to_rust_ty(ctx, &())?; - Ok(quote! { - [ #ty ; #len ] - }) - } - TypeKind::Enum(..) => { - let path = item.namespace_aware_canonical_path(ctx); - let path = Term::new(&path.join("::"), Span::call_site()); - Ok(quote!(#path)) - } - TypeKind::TemplateInstantiation(ref inst) => { - inst.try_to_rust_ty(ctx, item) - } - TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()), - TypeKind::TemplateAlias(..) | - TypeKind::Alias(..) => { - let template_params = item.used_template_params(ctx) - .unwrap_or(vec![]) - .into_iter() - .filter(|param| param.is_template_param(ctx, &())) - .collect::>(); - - let spelling = self.name().expect("Unnamed alias?"); - if item.is_opaque(ctx, &()) && !template_params.is_empty() { - self.try_to_opaque(ctx, item) - } else if let Some(ty) = utils::type_from_named( - ctx, - spelling, - ) - { - Ok(ty) - } else { - utils::build_path(item, ctx) - } - } - TypeKind::Comp(ref info) => { - let template_params = item.used_template_params(ctx); - if info.has_non_type_template_params() || - (item.is_opaque(ctx, &()) && template_params.is_some()) - { - return self.try_to_opaque(ctx, item); - } - - utils::build_path(item, ctx) - } - TypeKind::Opaque => self.try_to_opaque(ctx, item), - TypeKind::BlockPointer => { - let void = raw_type(ctx, "c_void"); - Ok(void.to_ptr( - /* is_const = */ - false - )) - } - TypeKind::Pointer(inner) | - TypeKind::Reference(inner) => { - let is_const = self.is_const() || ctx.resolve_type(inner).is_const(); - - let inner = inner.into_resolver().through_type_refs().resolve(ctx); - let inner_ty = inner.expect_type(); - - // Regardless if we can properly represent the inner type, we - // should always generate a proper pointer here, so use - // infallible conversion of the inner type. - let mut ty = inner.to_rust_ty_or_opaque(ctx, &()); - ty.append_implicit_template_params(ctx, inner); - - // Avoid the first function pointer level, since it's already - // represented in Rust. - if inner_ty.canonical_type(ctx).is_function() { - Ok(ty) - } else { - Ok(ty.to_ptr(is_const)) - } - } - TypeKind::TypeParam => { - let name = item.canonical_name(ctx); - let ident = ctx.rust_ident(&name); - Ok(quote! { - #ident - }) - } - TypeKind::ObjCSel => { - Ok(quote! { - objc::runtime::Sel - }) - } - TypeKind::ObjCId | - TypeKind::ObjCInterface(..) => Ok(quote! { - id - }), - ref u @ TypeKind::UnresolvedTypeRef(..) => { - unreachable!("Should have been resolved after parsing {:?}!", u) - } - } - } -} - -impl TryToOpaque for TemplateInstantiation { - type Extra = Item; - - fn try_get_layout( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> error::Result { - item.expect_type().layout(ctx).ok_or( - error::Error::NoLayoutForOpaqueBlob, - ) - } -} - -impl TryToRustTy for TemplateInstantiation { - type Extra = Item; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> error::Result { - if self.is_opaque(ctx, item) { - return Err(error::Error::InstantiationOfOpaqueType); - } - - let def = self.template_definition() - .into_resolver() - .through_type_refs() - .resolve(ctx); - - let mut ty = quote! {}; - let def_path = def.namespace_aware_canonical_path(ctx); - ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), Term::new("::", Span::call_site())); - - let def_params = match def.self_template_params(ctx) { - Some(params) => params, - None => { - // This can happen if we generated an opaque type for a partial - // template specialization, and we've hit an instantiation of - // that partial specialization. - extra_assert!( - def.is_opaque(ctx, &()) - ); - return Err(error::Error::InstantiationOfOpaqueType); - } - }; - - // TODO: If the definition type is a template class/struct - // definition's member template definition, it could rely on - // generic template parameters from its outer template - // class/struct. When we emit bindings for it, it could require - // *more* type arguments than we have here, and we will need to - // reconstruct them somehow. We don't have any means of doing - // that reconstruction at this time. - - let template_args = self.template_arguments() - .iter() - .zip(def_params.iter()) - // Only pass type arguments for the type parameters that - // the def uses. - .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param)) - .map(|(arg, _)| { - let arg = arg.into_resolver().through_type_refs().resolve(ctx); - let mut ty = arg.try_to_rust_ty(ctx, &())?; - ty.append_implicit_template_params(ctx, arg); - Ok(ty) - }) - .collect::>>()?; - - if template_args.is_empty() { - return Ok(ty); - } - - Ok(quote! { - #ty < #( #template_args ),* > - }) - } -} - -impl TryToRustTy for FunctionSig { - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result { - // TODO: we might want to consider ignoring the reference return value. - let ret = utils::fnsig_return_ty(ctx, &self); - let arguments = utils::fnsig_arguments(ctx, &self); - let abi = self.abi(); - - match abi { - Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => { - warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target"); - Ok(quote::Tokens::new()) - } - _ => { - Ok(quote! { - unsafe extern #abi fn ( #( #arguments ),* ) #ret - }) - } - } - } -} - -impl CodeGenerator for Function { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug!("::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - // We can't currently do anything with Internal functions so just - // avoid generating anything for them. - match self.linkage() { - Linkage::Internal => return, - Linkage::External => {} - } - - // Pure virtual methods have no actual symbol, so we can't generate - // something meaningful for them. - match self.kind() { - FunctionKind::Method(ref method_kind) if method_kind.is_pure_virtual() => { - return; - } - _ => {}, - } - - // Similar to static member variables in a class template, we can't - // generate bindings to template functions, because the set of - // instantiations is open ended and we have no way of knowing which - // monomorphizations actually exist. - let type_params = item.all_template_params(ctx); - if let Some(params) = type_params { - if !params.is_empty() { - return; - } - } - - let name = self.name(); - let mut canonical_name = item.canonical_name(ctx); - let mangled_name = self.mangled_name(); - - { - let seen_symbol_name = mangled_name.unwrap_or(&canonical_name); - - // TODO: Maybe warn here if there's a type/argument mismatch, or - // something? - if result.seen_function(seen_symbol_name) { - return; - } - result.saw_function(seen_symbol_name); - } - - let signature_item = ctx.resolve_item(self.signature()); - let signature = signature_item.kind().expect_type().canonical_type(ctx); - let signature = match *signature.kind() { - TypeKind::Function(ref sig) => sig, - _ => panic!("Signature kind is not a Function: {:?}", signature), - }; - - let args = utils::fnsig_arguments(ctx, signature); - let ret = utils::fnsig_return_ty(ctx, signature); - - let mut attributes = vec![]; - - if let Some(comment) = item.comment(ctx) { - attributes.push(attributes::doc(comment)); - } - - if let Some(mangled) = mangled_name { - attributes.push(attributes::link_name(mangled)); - } else if name != canonical_name { - attributes.push(attributes::link_name(name)); - } - - // Handle overloaded functions by giving each overload its own unique - // suffix. - let times_seen = result.overload_number(&canonical_name); - if times_seen > 0 { - write!(&mut canonical_name, "{}", times_seen).unwrap(); - } - - let abi = match signature.abi() { - Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => { - warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target"); - return; - } - Abi::Unknown(unknown_abi) => { - panic!( - "Invalid or unknown abi {:?} for function {:?} ({:?})", - unknown_abi, - canonical_name, - self - ); - } - abi => abi, - }; - - let ident = ctx.rust_ident(canonical_name); - let tokens = quote!( extern #abi { - #(#attributes)* - pub fn #ident ( #( #args ),* ) #ret; - }); - result.push(tokens); - } -} - - -fn objc_method_codegen( - ctx: &BindgenContext, - method: &ObjCMethod, - class_name: Option<&str>, - prefix: &str, -) -> (quote::Tokens, quote::Tokens) { - let signature = method.signature(); - let fn_args = utils::fnsig_arguments(ctx, signature); - let fn_ret = utils::fnsig_return_ty(ctx, signature); - - let sig = if method.is_class_method() { - let fn_args = fn_args.clone(); - quote! { - ( #( #fn_args ),* ) #fn_ret - } - } else { - let fn_args = fn_args.clone(); - let args = iter::once(quote! { self }) - .chain(fn_args.into_iter()); - quote! { - ( #( #args ),* ) #fn_ret - } - }; - - let methods_and_args = method.format_method_call(&fn_args); - - let body = if method.is_class_method() { - let class_name = class_name - .expect("Generating a class method without class name?") - .to_owned(); - let expect_msg = proc_macro2::Literal::string(&format!("Couldn't find {}", class_name)); - quote! { - msg_send!(objc::runtime::Class::get(#class_name).expect(#expect_msg), #methods_and_args) - } - } else { - quote! { - msg_send!(self, #methods_and_args) - } - }; - - let method_name = ctx.rust_ident(format!("{}{}", prefix, method.rust_name())); - - ( - quote! { - unsafe fn #method_name #sig { - #body - } - }, - quote! { - unsafe fn #method_name #sig ; - } - ) -} - -impl CodeGenerator for ObjCInterface { - type Extra = Item; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) { - debug_assert!(item.is_enabled_for_codegen(ctx)); - - let mut impl_items = vec![]; - let mut trait_items = vec![]; - - for method in self.methods() { - let (impl_item, trait_item) = - objc_method_codegen(ctx, method, None, ""); - impl_items.push(impl_item); - trait_items.push(trait_item) - } - - let instance_method_names: Vec<_> = self.methods() - .iter() - .map({ - |m| m.rust_name() - }) - .collect(); - - for class_method in self.class_methods() { - let ambiquity = - instance_method_names.contains(&class_method.rust_name()); - let prefix = if ambiquity { "class_" } else { "" }; - let (impl_item, trait_item) = objc_method_codegen( - ctx, - class_method, - Some(self.name()), - prefix, - ); - impl_items.push(impl_item); - trait_items.push(trait_item) - } - - let trait_name = ctx.rust_ident(self.rust_name()); - - let trait_block = quote! { - pub trait #trait_name { - #( #trait_items )* - } - }; - - let ty_for_impl = quote! { - id - }; - let impl_block = quote! { - impl #trait_name for #ty_for_impl { - #( #impl_items )* - } - }; - - result.push(trait_block); - result.push(impl_block); - result.saw_objc(); - } -} - -pub(crate) fn codegen(context: BindgenContext) -> (Vec, BindgenOptions) { - context.gen(|context| { - let _t = context.timer("codegen"); - let counter = Cell::new(0); - let mut result = CodegenResult::new(&counter); - - debug!("codegen: {:?}", context.options()); - - let codegen_items = context.codegen_items(); - if context.options().emit_ir { - for &id in codegen_items { - let item = context.resolve_item(id); - println!("ir: {:?} = {:#?}", id, item); - } - } - - if let Some(path) = context.options().emit_ir_graphviz.as_ref() { - match dot::write_dot_file(context, path) { - Ok(()) => info!("Your dot file was generated successfully into: {}", path), - Err(e) => error!("{}", e), - } - } - - context.resolve_item(context.root_module()) - .codegen(context, &mut result, &()); - - result.items - }) -} - -mod utils { - use super::{ToRustTyOrOpaque, error}; - use ir::context::BindgenContext; - use ir::function::FunctionSig; - use ir::item::{Item, ItemCanonicalPath}; - use ir::ty::TypeKind; - use quote; - use proc_macro2::{Term, Span}; - use std::mem; - - pub fn prepend_bitfield_unit_type(result: &mut Vec) { - let bitfield_unit_type = Term::new(include_str!("./bitfield_unit.rs"), Span::call_site()); - let bitfield_unit_type = quote!(#bitfield_unit_type); - - let items = vec![bitfield_unit_type]; - let old_items = mem::replace(result, items); - result.extend(old_items); - } - - pub fn prepend_objc_header( - ctx: &BindgenContext, - result: &mut Vec, - ) { - let use_objc = if ctx.options().objc_extern_crate { - quote! { - #[macro_use] - extern crate objc; - } - } else { - quote! { - use objc; - } - }; - - let id_type = quote! { - #[allow(non_camel_case_types)] - pub type id = *mut objc::runtime::Object; - }; - - let items = vec![use_objc, id_type]; - let old_items = mem::replace(result, items); - result.extend(old_items.into_iter()); - } - - pub fn prepend_union_types( - ctx: &BindgenContext, - result: &mut Vec, - ) { - let prefix = ctx.trait_prefix(); - - // TODO(emilio): The fmt::Debug impl could be way nicer with - // std::intrinsics::type_name, but... - let union_field_decl = quote! { - #[repr(C)] - pub struct __BindgenUnionField(::#prefix::marker::PhantomData); - }; - - let union_field_impl = quote! { - impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::#prefix::marker::PhantomData) - } - - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::#prefix::mem::transmute(self) - } - - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::#prefix::mem::transmute(self) - } - } - }; - - let union_field_default_impl = quote! { - impl ::#prefix::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } - } - }; - - let union_field_clone_impl = quote! { - impl ::#prefix::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } - } - }; - - let union_field_copy_impl = quote! { - impl ::#prefix::marker::Copy for __BindgenUnionField {} - }; - - let union_field_debug_impl = quote! { - impl ::#prefix::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter) - -> ::#prefix::fmt::Result { - fmt.write_str("__BindgenUnionField") - } - } - }; - - // The actual memory of the filed will be hashed, so that's why these - // field doesn't do anything with the hash. - let union_field_hash_impl = quote! { - impl ::#prefix::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) { - } - } - }; - - let union_field_partialeq_impl = quote! { - impl ::#prefix::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } - } - }; - - let union_field_eq_impl = quote! { - impl ::#prefix::cmp::Eq for __BindgenUnionField { - } - }; - - let items = vec![union_field_decl, - union_field_impl, - union_field_default_impl, - union_field_clone_impl, - union_field_copy_impl, - union_field_debug_impl, - union_field_hash_impl, - union_field_partialeq_impl, - union_field_eq_impl]; - - let old_items = mem::replace(result, items); - result.extend(old_items.into_iter()); - } - - pub fn prepend_incomplete_array_types( - ctx: &BindgenContext, - result: &mut Vec, - ) { - let prefix = ctx.trait_prefix(); - - let incomplete_array_decl = quote! { - #[repr(C)] - #[derive(Default)] - pub struct __IncompleteArrayField( - ::#prefix::marker::PhantomData); - }; - - let incomplete_array_impl = quote! { - impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::#prefix::marker::PhantomData) - } - - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::#prefix::mem::transmute(self) - } - - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::#prefix::mem::transmute(self) - } - - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::#prefix::slice::from_raw_parts(self.as_ptr(), len) - } - - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } - } - }; - - let incomplete_array_debug_impl = quote! { - impl ::#prefix::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter) - -> ::#prefix::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } - } - }; - - let incomplete_array_clone_impl = quote! { - impl ::#prefix::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } - } - }; - - let incomplete_array_copy_impl = quote! { - impl ::#prefix::marker::Copy for __IncompleteArrayField {} - }; - - let items = vec![incomplete_array_decl, - incomplete_array_impl, - incomplete_array_debug_impl, - incomplete_array_clone_impl, - incomplete_array_copy_impl]; - - let old_items = mem::replace(result, items); - result.extend(old_items.into_iter()); - } - - pub fn prepend_complex_type( - result: &mut Vec, - ) { - let complex_type = quote! { - #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] - #[repr(C)] - pub struct __BindgenComplex { - pub re: T, - pub im: T - } - }; - - let items = vec![complex_type]; - let old_items = mem::replace(result, items); - result.extend(old_items.into_iter()); - } - - pub fn build_path( - item: &Item, - ctx: &BindgenContext, - ) -> error::Result { - use proc_macro2::{Term, Span}; - - let path = item.namespace_aware_canonical_path(ctx); - let path = Term::new(&path.join("::"), Span::call_site()); - let tokens = quote! {#path}; - //tokens.append_separated(path, "::"); - - Ok(tokens) - } - - fn primitive_ty(ctx: &BindgenContext, name: &str) -> quote::Tokens { - let ident = ctx.rust_ident_raw(name); - quote! { - #ident - } - } - - pub fn type_from_named( - ctx: &BindgenContext, - name: &str, - ) -> Option { - // FIXME: We could use the inner item to check this is really a - // primitive type but, who the heck overrides these anyway? - Some(match name { - "int8_t" => primitive_ty(ctx, "i8"), - "uint8_t" => primitive_ty(ctx, "u8"), - "int16_t" => primitive_ty(ctx, "i16"), - "uint16_t" => primitive_ty(ctx, "u16"), - "int32_t" => primitive_ty(ctx, "i32"), - "uint32_t" => primitive_ty(ctx, "u32"), - "int64_t" => primitive_ty(ctx, "i64"), - "uint64_t" => primitive_ty(ctx, "u64"), - - "uintptr_t" | "size_t" => primitive_ty(ctx, "usize"), - - "intptr_t" | "ptrdiff_t" | "ssize_t" => primitive_ty(ctx, "isize"), - _ => return None, - }) - } - - pub fn fnsig_return_ty( - ctx: &BindgenContext, - sig: &FunctionSig, - ) -> quote::Tokens { - let return_item = ctx.resolve_item(sig.return_type()); - if let TypeKind::Void = *return_item.kind().expect_type().kind() { - quote! { } - } else { - let ret_ty = return_item.to_rust_ty_or_opaque(ctx, &()); - quote! { - -> #ret_ty - } - } - } - - pub fn fnsig_arguments( - ctx: &BindgenContext, - sig: &FunctionSig, - ) -> Vec { - use super::ToPtr; - - let mut unnamed_arguments = 0; - let mut args = sig.argument_types().iter().map(|&(ref name, ty)| { - let arg_item = ctx.resolve_item(ty); - let arg_ty = arg_item.kind().expect_type(); - - // From the C90 standard[1]: - // - // A declaration of a parameter as "array of type" shall be - // adjusted to "qualified pointer to type", where the type - // qualifiers (if any) are those specified within the [ and ] of - // the array type derivation. - // - // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html - let arg_ty = match *arg_ty.canonical_type(ctx).kind() { - TypeKind::Array(t, _) => { - t.to_rust_ty_or_opaque(ctx, &()) - .to_ptr(ctx.resolve_type(t).is_const()) - }, - TypeKind::Pointer(inner) => { - let inner = ctx.resolve_item(inner); - let inner_ty = inner.expect_type(); - if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() { - quote! { - id - } - } else { - arg_item.to_rust_ty_or_opaque(ctx, &()) - } - }, - _ => { - arg_item.to_rust_ty_or_opaque(ctx, &()) - } - }; - - let arg_name = match *name { - Some(ref name) => ctx.rust_mangle(name).into_owned(), - None => { - unnamed_arguments += 1; - format!("arg{}", unnamed_arguments) - } - }; - - assert!(!arg_name.is_empty()); - let arg_name = ctx.rust_ident(arg_name); - - quote! { - #arg_name : #arg_ty - } - }).collect::>(); - - if sig.is_variadic() { - args.push(quote! { ... }) - } - - args - } -} diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs deleted file mode 100644 index 6de7e03069..0000000000 --- a/src/codegen/struct_layout.rs +++ /dev/null @@ -1,364 +0,0 @@ -//! Helpers for code generation that need struct layout - -use super::helpers; - -use ir::comp::CompInfo; -use ir::context::BindgenContext; -use ir::layout::Layout; -use ir::ty::{Type, TypeKind}; -use quote; -use proc_macro2::{Term, Span}; -use std::cmp; - -/// Trace the layout of struct. -#[derive(Debug)] -pub struct StructLayoutTracker<'a> { - name: &'a str, - ctx: &'a BindgenContext, - comp: &'a CompInfo, - is_packed: bool, - latest_offset: usize, - padding_count: usize, - latest_field_layout: Option, - max_field_align: usize, - last_field_was_bitfield: bool, -} - -/// Returns a size aligned to a given value. -pub fn align_to(size: usize, align: usize) -> usize { - if align == 0 { - return size; - } - - let rem = size % align; - if rem == 0 { - return size; - } - - size + align - rem -} - -/// Returns the lower power of two byte count that can hold at most n bits. -pub fn bytes_from_bits_pow2(mut n: usize) -> usize { - if n == 0 { - return 0; - } - - if n <= 8 { - return 1; - } - - if !n.is_power_of_two() { - n = n.next_power_of_two(); - } - - n / 8 -} - -#[test] -fn test_align_to() { - assert_eq!(align_to(1, 1), 1); - assert_eq!(align_to(1, 2), 2); - assert_eq!(align_to(1, 4), 4); - assert_eq!(align_to(5, 1), 5); - assert_eq!(align_to(17, 4), 20); -} - -#[test] -fn test_bytes_from_bits_pow2() { - assert_eq!(bytes_from_bits_pow2(0), 0); - for i in 1..9 { - assert_eq!(bytes_from_bits_pow2(i), 1); - } - for i in 9..17 { - assert_eq!(bytes_from_bits_pow2(i), 2); - } - for i in 17..33 { - assert_eq!(bytes_from_bits_pow2(i), 4); - } -} - -impl<'a> StructLayoutTracker<'a> { - pub fn new( - ctx: &'a BindgenContext, - comp: &'a CompInfo, - ty: &'a Type, - name: &'a str, - ) -> Self { - StructLayoutTracker { - name: name, - ctx: ctx, - comp: comp, - is_packed: comp.is_packed(ctx, &ty.layout(ctx)), - latest_offset: 0, - padding_count: 0, - latest_field_layout: None, - max_field_align: 0, - last_field_was_bitfield: false, - } - } - - pub fn saw_vtable(&mut self) { - debug!("saw vtable for {}", self.name); - - let ptr_size = self.ctx.target_pointer_size(); - self.latest_offset += ptr_size; - self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size)); - self.max_field_align = ptr_size; - } - - pub fn saw_base(&mut self, base_ty: &Type) { - debug!("saw base for {}", self.name); - if let Some(layout) = base_ty.layout(self.ctx) { - self.align_to_latest_field(layout); - - self.latest_offset += self.padding_bytes(layout) + layout.size; - self.latest_field_layout = Some(layout); - self.max_field_align = cmp::max(self.max_field_align, layout.align); - } - } - - pub fn saw_bitfield_unit(&mut self, layout: Layout) { - debug!("saw bitfield unit for {}: {:?}", self.name, layout); - - self.align_to_latest_field(layout); - - self.latest_offset += layout.size; - - debug!( - "Offset: : {} -> {}", - self.latest_offset - layout.size, - self.latest_offset - ); - - self.latest_field_layout = Some(layout); - self.last_field_was_bitfield = true; - // NB: We intentionally don't update the max_field_align here, since our - // bitfields code doesn't necessarily guarantee it, so we need to - // actually generate the dummy alignment. - } - - pub fn saw_union(&mut self, layout: Layout) { - debug!("saw union for {}: {:?}", self.name, layout); - self.align_to_latest_field(layout); - - self.latest_offset += self.padding_bytes(layout) + layout.size; - self.latest_field_layout = Some(layout); - self.max_field_align = cmp::max(self.max_field_align, layout.align); - } - - /// Add a padding field if necessary for a given new field _before_ adding - /// that field. - pub fn pad_field( - &mut self, - field_name: &str, - field_ty: &Type, - field_offset: Option, - ) -> Option { - let mut field_layout = field_ty.layout(self.ctx)?; - - if let TypeKind::Array(inner, len) = - *field_ty.canonical_type(self.ctx).kind() - { - // FIXME(emilio): As an _ultra_ hack, we correct the layout returned - // by arrays of structs that have a bigger alignment than what we - // can support. - // - // This means that the structs in the array are super-unsafe to - // access, since they won't be properly aligned, but there's not too - // much we can do about it. - if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) { - if layout.align > self.ctx.target_pointer_size() { - field_layout.size = - align_to(layout.size, layout.align) * len; - field_layout.align = self.ctx.target_pointer_size(); - } - } - } - - let will_merge_with_bitfield = self.align_to_latest_field(field_layout); - - let padding_layout = if self.is_packed { - None - } else { - let padding_bytes = match field_offset { - Some(offset) if offset / 8 > self.latest_offset => { - offset / 8 - self.latest_offset - } - _ if will_merge_with_bitfield || field_layout.align == 0 => 0, - _ => self.padding_bytes(field_layout), - }; - - // Otherwise the padding is useless. - let need_padding = padding_bytes >= field_layout.align || - field_layout.align > self.ctx.target_pointer_size(); - - self.latest_offset += padding_bytes; - - debug!( - "Offset: : {} -> {}", - self.latest_offset - padding_bytes, - self.latest_offset - ); - - debug!( - "align field {} to {}/{} with {} padding bytes {:?}", - field_name, - self.latest_offset, - field_offset.unwrap_or(0) / 8, - padding_bytes, - field_layout - ); - - if need_padding && padding_bytes != 0 { - Some(Layout::new( - padding_bytes, - cmp::min(field_layout.align, self.ctx.target_pointer_size()) - )) - } else { - None - } - }; - - self.latest_offset += field_layout.size; - self.latest_field_layout = Some(field_layout); - self.max_field_align = - cmp::max(self.max_field_align, field_layout.align); - self.last_field_was_bitfield = false; - - debug!( - "Offset: {}: {} -> {}", - field_name, - self.latest_offset - field_layout.size, - self.latest_offset - ); - - padding_layout.map(|layout| self.padding_field(layout)) - } - - pub fn pad_struct(&mut self, layout: Layout) -> Option { - debug!( - "pad_struct:\n\tself = {:#?}\n\tlayout = {:#?}", - self, - layout - ); - - if layout.size < self.latest_offset { - error!( - "Calculated wrong layout for {}, too more {} bytes", - self.name, - self.latest_offset - layout.size - ); - return None; - } - - let padding_bytes = layout.size - self.latest_offset; - - // We always pad to get to the correct size if the struct is one of - // those we can't align properly. - // - // Note that if the last field we saw was a bitfield, we may need to pad - // regardless, because bitfields don't respect alignment as strictly as - // other fields. - if padding_bytes > 0 && - (padding_bytes >= layout.align || - (self.last_field_was_bitfield && - padding_bytes >= - self.latest_field_layout.unwrap().align) || - layout.align > self.ctx.target_pointer_size()) - { - let layout = if self.is_packed { - Layout::new(padding_bytes, 1) - } else if self.last_field_was_bitfield || - layout.align > self.ctx.target_pointer_size() - { - // We've already given up on alignment here. - Layout::for_size(self.ctx, padding_bytes) - } else { - Layout::new(padding_bytes, layout.align) - }; - - debug!("pad bytes to struct {}, {:?}", self.name, layout); - - Some(self.padding_field(layout)) - } else { - None - } - } - - pub fn requires_explicit_align(&self, layout: Layout) -> bool { - if self.max_field_align >= layout.align { - return false; - } - // At this point we require explicit alignment, but we may not be able - // to generate the right bits, let's double check. - if self.ctx.options().rust_features().repr_align { - return true; - } - - // We can only generate up-to a word of alignment unless we support - // repr(align). - layout.align <= self.ctx.target_pointer_size() - } - - fn padding_bytes(&self, layout: Layout) -> usize { - align_to(self.latest_offset, layout.align) - self.latest_offset - } - - fn padding_field(&mut self, layout: Layout) -> quote::Tokens { - let ty = helpers::blob(layout); - let padding_count = self.padding_count; - - self.padding_count += 1; - - let padding_field_name = Term::new(&format!("__bindgen_padding_{}", padding_count), Span::call_site()); - - self.max_field_align = cmp::max(self.max_field_align, layout.align); - - quote! { - pub #padding_field_name : #ty , - } - } - - /// Returns whether the new field is known to merge with a bitfield. - /// - /// This is just to avoid doing the same check also in pad_field. - fn align_to_latest_field(&mut self, new_field_layout: Layout) -> bool { - if self.is_packed { - // Skip to align fields when packed. - return false; - } - - let layout = match self.latest_field_layout { - Some(l) => l, - None => return false, - }; - - // If it was, we may or may not need to align, depending on what the - // current field alignment and the bitfield size and alignment are. - debug!( - "align_to_bitfield? {}: {:?} {:?}", - self.last_field_was_bitfield, - layout, - new_field_layout - ); - - // Avoid divide-by-zero errors if align is 0. - let align = cmp::max(1, layout.align); - - if self.last_field_was_bitfield && - new_field_layout.align <= layout.size % align && - new_field_layout.size <= layout.size % align - { - // The new field will be coalesced into some of the remaining bits. - // - // FIXME(emilio): I think this may not catch everything? - debug!("Will merge with bitfield"); - return true; - } - - // Else, just align the obvious way. - self.latest_offset += self.padding_bytes(layout); - return false; - } -} diff --git a/src/extra_assertions.rs b/src/extra_assertions.rs deleted file mode 100644 index b89c718a48..0000000000 --- a/src/extra_assertions.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Macros for defining extra assertions that should only be checked in testing -//! and/or CI when the `testing_only_extra_assertions` feature is enabled. - -#[macro_export] -macro_rules! extra_assert { - ( $cond:expr ) => { - if cfg!(feature = "testing_only_extra_assertions") { - assert!($cond); - } - }; - ( $cond:expr , $( $arg:tt )+ ) => { - if cfg!(feature = "testing_only_extra_assertions") { - assert!($cond, $( $arg )* ) - } - }; -} - -#[macro_export] -macro_rules! extra_assert_eq { - ( $lhs:expr , $rhs:expr ) => { - if cfg!(feature = "testing_only_extra_assertions") { - assert_eq!($lhs, $rhs); - } - }; - ( $lhs:expr , $rhs:expr , $( $arg:tt )+ ) => { - if cfg!(feature = "testing_only_extra_assertions") { - assert!($lhs, $rhs, $( $arg )* ); - } - }; -} diff --git a/src/features.rs b/src/features.rs deleted file mode 100644 index 93ebbc34b8..0000000000 --- a/src/features.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! Contains code for selecting features - -#![deny(missing_docs)] -#![deny(warnings)] -#![deny(unused_extern_crates)] - -use std::io; -use std::str::FromStr; - -/// Define RustTarget struct definition, Default impl, and conversions -/// between RustTarget and String. -macro_rules! rust_target_def { - ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => { - /// Represents the version of the Rust language to target. - /// - /// To support a beta release, use the corresponding stable release. - /// - /// This enum will have more variants added as necessary. - #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)] - #[allow(non_camel_case_types)] - pub enum RustTarget { - $( - $( - #[$attr] - )* - $release, - )* - } - - impl Default for RustTarget { - /// Gives the latest stable Rust version - fn default() -> RustTarget { - LATEST_STABLE_RUST - } - } - - impl FromStr for RustTarget { - type Err = io::Error; - - /// Create a `RustTarget` from a string. - /// - /// * The stable/beta versions of Rust are of the form "1.0", - /// "1.19", etc. - /// * The nightly version should be specified with "nightly". - fn from_str(s: &str) -> Result { - match s.as_ref() { - $( - stringify!($value) => Ok(RustTarget::$release), - )* - _ => Err( - io::Error::new( - io::ErrorKind::InvalidInput, - concat!( - "Got an invalid rust target. Accepted values ", - "are of the form ", - "\"1.0\" or \"nightly\"."))), - } - } - } - - impl From for String { - fn from(target: RustTarget) -> Self { - match target { - $( - RustTarget::$release => stringify!($value), - )* - }.into() - } - } - } -} - -/// Defines an array slice with all RustTarget values -macro_rules! rust_target_values_def { - ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => { - /// Strings of allowed `RustTarget` values - pub static RUST_TARGET_STRINGS: &'static [&str] = &[ - $( - stringify!($value), - )* - ]; - } -} - -/// Defines macro which takes a macro -macro_rules! rust_target_base { - ( $x_macro:ident ) => { - $x_macro!( - /// Rust stable 1.0 - => Stable_1_0 => 1.0; - /// Rust stable 1.19 - => Stable_1_19 => 1.19; - /// Rust stable 1.20 - => Stable_1_20 => 1.20; - /// Rust stable 1.21 - => Stable_1_21 => 1.21; - /// Rust stable 1.25 - => Stable_1_25 => 1.25; - /// Nightly rust - => Nightly => nightly; - ); - } -} - -rust_target_base!(rust_target_def); -rust_target_base!(rust_target_values_def); - -/// Latest stable release of Rust -pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_21; - -/// Create RustFeatures struct definition, new(), and a getter for each field -macro_rules! rust_feature_def { - ( $( $( #[$attr:meta] )* => $feature:ident; )* ) => { - /// Features supported by a rust target - #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] - pub struct RustFeatures { - $( - $( - #[$attr] - )* - pub $feature: bool, - )* - } - - impl RustFeatures { - /// Gives a RustFeatures struct with all features disabled - fn new() -> Self { - RustFeatures { - $( - $feature: false, - )* - } - } - } - } -} - -rust_feature_def!( - /// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md)) - => untagged_union; - /// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202)) - => thiscall_abi; - /// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690)) - => builtin_clone_impls; - /// repr(align) https://github.com/rust-lang/rust/pull/47006 - => repr_align; - /// associated constants https://github.com/rust-lang/rust/issues/29646 - => associated_const; -); - -impl From for RustFeatures { - fn from(rust_target: RustTarget) -> Self { - let mut features = RustFeatures::new(); - - if rust_target >= RustTarget::Stable_1_19 { - features.untagged_union = true; - } - - if rust_target >= RustTarget::Stable_1_20 { - features.associated_const = true; - } - - if rust_target >= RustTarget::Stable_1_21 { - features.builtin_clone_impls = true; - } - - if rust_target >= RustTarget::Stable_1_25 { - features.repr_align = true; - } - - if rust_target >= RustTarget::Nightly { - features.thiscall_abi = true; - } - - features - } -} - -impl Default for RustFeatures { - fn default() -> Self { - let default_rust_target: RustTarget = Default::default(); - Self::from(default_rust_target) - } -} - -#[cfg(test)] -mod test { -#![allow(unused_imports)] - use super::*; - - fn test_target(target_str: &str, target: RustTarget) { - let target_string: String = target.into(); - assert_eq!(target_str, target_string); - assert_eq!(target, RustTarget::from_str(target_str).unwrap()); - } - - #[test] - fn str_to_target() { - test_target("1.0", RustTarget::Stable_1_0); - test_target("1.19", RustTarget::Stable_1_19); - test_target("1.21", RustTarget::Stable_1_21); - test_target("1.25", RustTarget::Stable_1_25); - test_target("nightly", RustTarget::Nightly); - } -} diff --git a/src/ir/analysis/derive_copy.rs b/src/ir/analysis/derive_copy.rs deleted file mode 100644 index 69725ead49..0000000000 --- a/src/ir/analysis/derive_copy.rs +++ /dev/null @@ -1,356 +0,0 @@ -//! Determining which types for which we can emit `#[derive(Copy)]`. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::CompKind; -use ir::comp::Field; -use ir::comp::FieldMethods; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::CanTriviallyDeriveCopy; -use ir::item::IsOpaque; -use ir::template::TemplateParameters; -use ir::traversal::EdgeKind; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; - -/// An analysis that finds for each IR item whether copy cannot be derived. -/// -/// We use the monotone constraint function `cannot_derive_copy`, defined as -/// follows: -/// -/// * If T is Opaque and layout of the type is known, get this layout as opaque -/// type and check whether it can be derived using trivial checks. -/// * If T is Array type, copy cannot be derived if the length of the array is -/// larger than the limit or the type of data the array contains cannot derive -/// copy. -/// * If T is a type alias, a templated alias or an indirection to another type, -/// copy cannot be derived if the type T refers to cannot be derived copy. -/// * If T is a compound type, copy cannot be derived if any of its base member -/// or field cannot be derived copy. -/// * If T is an instantiation of an abstract template definition, T cannot be -/// derived copy if any of the template arguments or template definition -/// cannot derive copy. -#[derive(Debug, Clone)] -pub struct CannotDeriveCopy<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set cannot derive copy. - cannot_derive_copy: HashSet, - - // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_copy` set, then each of - // the ids in Vec need to be considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // can derive copy or not. - dependencies: HashMap>, -} - -impl<'ctx> CannotDeriveCopy<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type can derive - // copy or not. - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>(&mut self, id: Id) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} into the cannot_derive_copy set", id); - - let was_not_already_in_set = self.cannot_derive_copy.insert(id); - assert!( - was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id - ); - - ConstrainResult::Changed - } - - /// A type is not `Copy` if we've determined it is not copy, or if it is - /// blacklisted. - fn is_not_copy>(&self, id: Id) -> bool { - let id = id.into(); - self.cannot_derive_copy.contains(&id) || - !self.ctx.whitelisted_items().contains(&id) - } -} - -impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashSet; - - fn new(ctx: &'ctx BindgenContext) -> CannotDeriveCopy<'ctx> { - let cannot_derive_copy = HashSet::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - CannotDeriveCopy { - ctx, - cannot_derive_copy, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if self.cannot_derive_copy.contains(&id) { - trace!(" already know it cannot derive Copy"); - return ConstrainResult::Same; - } - - // If an item is reachable from the whitelisted items set, but isn't - // itself whitelisted, then it must be blacklisted. We assume that - // blacklisted items are not `Copy`, since they are presumably - // blacklisted because they are too complicated for us to understand. - if !self.ctx.whitelisted_items().contains(&id) { - trace!(" blacklisted items are assumed not to be Copy"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } - }; - - if self.ctx.no_copy_by_name(&item) { - return self.insert(id); - } - - if item.is_opaque(self.ctx, &()) { - let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_copy() - }); - return if layout_can_derive { - trace!(" we can trivially derive Copy for the layout"); - ConstrainResult::Same - } else { - trace!(" we cannot derive Copy for the layout"); - self.insert(id) - }; - } - - match *ty.kind() { - // Handle the simple cases. These can derive copy without further - // information. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::TypeParam | - TypeKind::BlockPointer | - TypeKind::Pointer(..) | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!(" simple type that can always derive Copy"); - ConstrainResult::Same - } - - TypeKind::Array(t, len) => { - let cant_derive_copy = self.is_not_copy(t); - if cant_derive_copy { - trace!( - " arrays of T for which we cannot derive Copy \ - also cannot derive Copy" - ); - return self.insert(id); - } - - if len > 0 { - trace!(" array can derive Copy with positive length"); - ConstrainResult::Same - } else { - trace!(" array cannot derive Copy with 0 length"); - self.insert(id) - } - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - let cant_derive_copy = self.is_not_copy(t); - if cant_derive_copy { - trace!( - " arrays of T for which we cannot derive Copy \ - also cannot derive Copy" - ); - return self.insert(id); - } - trace!( - " aliases and type refs to T which can derive \ - Copy can also derive Copy" - ); - ConstrainResult::Same - } - - TypeKind::Comp(ref info) => { - assert!( - !info.has_non_type_template_params(), - "The early ty.is_opaque check should have handled this case" - ); - - // NOTE: Take into account that while unions in C and C++ are copied by - // default, the may have an explicit destructor in C++, so we can't - // defer this check just for the union case. - if self.ctx.lookup_has_destructor(id.expect_type_id(self.ctx)) { - trace!(" comp has destructor which cannot derive copy"); - return self.insert(id); - } - - if info.kind() == CompKind::Union { - if !self.ctx.options().rust_features().untagged_union { - // NOTE: If there's no template parameters we can derive - // copy unconditionally, since arrays are magical for - // rustc, and __BindgenUnionField always implements - // copy. - trace!( - " comp can always derive debug if it's a Union and no template parameters" - ); - return ConstrainResult::Same; - } - - // https://github.com/rust-lang/rust/issues/36640 - if info.self_template_params(self.ctx).is_some() || - item.used_template_params(self.ctx).is_some() - { - trace!( - " comp cannot derive copy because issue 36640" - ); - return self.insert(id); - } - } - - let bases_cannot_derive = - info.base_members().iter().any(|base| { - self.is_not_copy(base.ty) - }); - if bases_cannot_derive { - trace!( - " base members cannot derive Copy, so we can't \ - either" - ); - return self.insert(id); - } - - let fields_cannot_derive = - info.fields().iter().any(|f| match *f { - Field::DataMember(ref data) => { - self.is_not_copy(data.ty()) - } - Field::Bitfields(ref bfu) => { - if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " we cannot derive Copy for a bitfield larger then \ - the limit" - ); - return true; - } - - bfu.bitfields().iter().any(|b| { - self.is_not_copy(b.ty()) - }) - } - }); - if fields_cannot_derive { - trace!(" fields cannot derive Copy, so we can't either"); - return self.insert(id); - } - - trace!(" comp can derive Copy"); - ConstrainResult::Same - } - - TypeKind::TemplateInstantiation(ref template) => { - let args_cannot_derive = - template.template_arguments().iter().any(|arg| { - self.is_not_copy(*arg) - }); - if args_cannot_derive { - trace!( - " template args cannot derive Copy, so \ - insantiation can't either" - ); - return self.insert(id); - } - - assert!( - !template.template_definition().is_opaque(self.ctx, &()), - "The early ty.is_opaque check should have handled this case" - ); - let def_cannot_derive = self.is_not_copy( - template.template_definition() - ); - if def_cannot_derive { - trace!( - " template definition cannot derive Copy, so \ - insantiation can't either" - ); - return self.insert(id); - } - - trace!(" template instantiation can derive Copy"); - ConstrainResult::Same - } - - TypeKind::Opaque => { - unreachable!( - "The early ty.is_opaque check should have handled this case" - ) - } - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashSet { - fn from(analysis: CannotDeriveCopy<'ctx>) -> Self { - analysis.cannot_derive_copy - } -} diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs deleted file mode 100644 index b191d37da4..0000000000 --- a/src/ir/analysis/derive_debug.rs +++ /dev/null @@ -1,369 +0,0 @@ -//! Determining which types for which we can emit `#[derive(Debug)]`. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::CompKind; -use ir::comp::Field; -use ir::comp::FieldMethods; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::CanTriviallyDeriveDebug; -use ir::item::IsOpaque; -use ir::traversal::EdgeKind; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; - -/// An analysis that finds for each IR item whether debug cannot be derived. -/// -/// We use the monotone constraint function `cannot_derive_debug`, defined as -/// follows: -/// -/// * If T is Opaque and layout of the type is known, get this layout as opaque -/// type and check whether it can be derived using trivial checks. -/// * If T is Array type, debug cannot be derived if the length of the array is -/// larger than the limit or the type of data the array contains cannot derive -/// debug. -/// * If T is a type alias, a templated alias or an indirection to another type, -/// debug cannot be derived if the type T refers to cannot be derived debug. -/// * If T is a compound type, debug cannot be derived if any of its base member -/// or field cannot be derived debug. -/// * If T is a pointer, T cannot be derived debug if T is a function pointer -/// and the function signature cannot be derived debug. -/// * If T is an instantiation of an abstract template definition, T cannot be -/// derived debug if any of the template arguments or template definition -/// cannot derive debug. -#[derive(Debug, Clone)] -pub struct CannotDeriveDebug<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set cannot derive debug. - cannot_derive_debug: HashSet, - - // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_debug` set, then each of the ids in Vec need to be - // considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // can derive debug or not. - dependencies: HashMap>, -} - -impl<'ctx> CannotDeriveDebug<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type can derive - // debug or not. - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>(&mut self, id: Id) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} into the cannot_derive_debug set", id); - - let was_not_already_in_set = self.cannot_derive_debug.insert(id); - assert!( - was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id - ); - - ConstrainResult::Changed - } - - /// A type is not `Debug` if we've determined it is not debug, or if it is - /// blacklisted. - fn is_not_debug>(&self, id: Id) -> bool { - let id = id.into(); - self.cannot_derive_debug.contains(&id) || - !self.ctx.whitelisted_items().contains(&id) - } -} - -impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashSet; - - fn new(ctx: &'ctx BindgenContext) -> CannotDeriveDebug<'ctx> { - let cannot_derive_debug = HashSet::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - CannotDeriveDebug { - ctx, - cannot_derive_debug, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if self.cannot_derive_debug.contains(&id) { - trace!(" already know it cannot derive Debug"); - return ConstrainResult::Same; - } - - // If an item is reachable from the whitelisted items set, but isn't - // itself whitelisted, then it must be blacklisted. We assume that - // blacklisted items are not `Copy`, since they are presumably - // blacklisted because they are too complicated for us to understand. - if !self.ctx.whitelisted_items().contains(&id) { - trace!(" blacklisted items are assumed not to be Debug"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } - }; - - if item.is_opaque(self.ctx, &()) { - let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_debug() - }); - return if layout_can_derive && - !(ty.is_union() && - self.ctx.options().rust_features().untagged_union) { - trace!(" we can trivially derive Debug for the layout"); - ConstrainResult::Same - } else { - trace!(" we cannot derive Debug for the layout"); - self.insert(id) - }; - } - - if ty.layout(self.ctx).map_or(false, |l| { - l.align > RUST_DERIVE_IN_ARRAY_LIMIT - }) - { - // We have to be conservative: the struct *could* have enough - // padding that we emit an array that is longer than - // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations - // into the IR and computed them before this analysis, then we could - // be precise rather than conservative here. - return self.insert(id); - } - - match *ty.kind() { - // Handle the simple cases. These can derive debug without further - // information. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::BlockPointer | - TypeKind::TypeParam | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!(" simple type that can always derive Debug"); - ConstrainResult::Same - } - - TypeKind::Array(t, len) => { - if self.is_not_debug(t) { - trace!( - " arrays of T for which we cannot derive Debug \ - also cannot derive Debug" - ); - return self.insert(id); - } - - if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!(" array is small enough to derive Debug"); - ConstrainResult::Same - } else { - trace!(" array is too large to derive Debug"); - self.insert(id) - } - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - if self.is_not_debug(t) { - trace!( - " aliases and type refs to T which cannot derive \ - Debug also cannot derive Debug" - ); - self.insert(id) - } else { - trace!( - " aliases and type refs to T which can derive \ - Debug can also derive Debug" - ); - ConstrainResult::Same - } - } - - TypeKind::Comp(ref info) => { - assert!( - !info.has_non_type_template_params(), - "The early ty.is_opaque check should have handled this case" - ); - - if info.kind() == CompKind::Union { - if self.ctx.options().rust_features().untagged_union { - trace!(" cannot derive Debug for Rust unions"); - return self.insert(id); - } - - if ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_debug() - }) - { - trace!(" union layout can trivially derive Debug"); - return ConstrainResult::Same; - } else { - trace!(" union layout cannot derive Debug"); - return self.insert(id); - } - } - - let bases_cannot_derive = - info.base_members().iter().any(|base| { - self.is_not_debug(base.ty) - }); - if bases_cannot_derive { - trace!( - " base members cannot derive Debug, so we can't \ - either" - ); - return self.insert(id); - } - - let fields_cannot_derive = - info.fields().iter().any(|f| match *f { - Field::DataMember(ref data) => { - self.is_not_debug(data.ty()) - } - Field::Bitfields(ref bfu) => { - if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " we cannot derive Debug for a bitfield larger then \ - the limit" - ); - return true; - } - - bfu.bitfields().iter().any(|b| { - self.is_not_debug(b.ty()) - }) - } - }); - if fields_cannot_derive { - trace!( - " fields cannot derive Debug, so we can't either" - ); - return self.insert(id); - } - - trace!(" comp can derive Debug"); - ConstrainResult::Same - } - - TypeKind::Pointer(inner) => { - let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); - if let TypeKind::Function(ref sig) = *inner_type.kind() { - if !sig.can_trivially_derive_debug() { - trace!( - " function pointer that can't trivially derive Debug" - ); - return self.insert(id); - } - } - trace!(" pointers can derive Debug"); - ConstrainResult::Same - } - - TypeKind::TemplateInstantiation(ref template) => { - let args_cannot_derive = - template.template_arguments().iter().any(|arg| { - self.is_not_debug(*arg) - }); - if args_cannot_derive { - trace!( - " template args cannot derive Debug, so \ - insantiation can't either" - ); - return self.insert(id); - } - - assert!( - !template.template_definition().is_opaque(self.ctx, &()), - "The early ty.is_opaque check should have handled this case" - ); - let def_cannot_derive = self.is_not_debug( - template.template_definition() - ); - if def_cannot_derive { - trace!( - " template definition cannot derive Debug, so \ - insantiation can't either" - ); - return self.insert(id); - } - - trace!(" template instantiation can derive Debug"); - ConstrainResult::Same - } - - TypeKind::Opaque => { - unreachable!( - "The early ty.is_opaque check should have handled this case" - ) - } - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashSet { - fn from(analysis: CannotDeriveDebug<'ctx>) -> Self { - analysis.cannot_derive_debug - } -} diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs deleted file mode 100644 index e319166d32..0000000000 --- a/src/ir/analysis/derive_default.rs +++ /dev/null @@ -1,407 +0,0 @@ -//! Determining which types for which we can emit `#[derive(Default)]`. - -use super::{ConstrainResult, HasVtable, MonotoneFramework}; -use ir::comp::CompKind; -use ir::comp::Field; -use ir::comp::FieldMethods; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::CanTriviallyDeriveDefault; -use ir::item::IsOpaque; -use ir::item::ItemSet; -use ir::traversal::EdgeKind; -use ir::traversal::Trace; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; - -/// An analysis that finds for each IR item whether default cannot be derived. -/// -/// We use the monotone constraint function `cannot_derive_default`, defined as -/// follows: -/// -/// * If T is Opaque and layout of the type is known, get this layout as opaque -/// type and check whether it can be derived using trivial checks. -/// * If T is Array type, default cannot be derived if the length of the array is -/// larger than the limit or the type of data the array contains cannot derive -/// default. -/// * If T is a type alias, a templated alias or an indirection to another type, -/// default cannot be derived if the type T refers to cannot be derived default. -/// * If T is a compound type, default cannot be derived if any of its base member -/// or field cannot be derived default. -#[derive(Debug, Clone)] -pub struct CannotDeriveDefault<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set cannot derive default. - cannot_derive_default: HashSet, - - // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_default` set, then each of the ids in Vec need to be - // considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // can derive default or not. - dependencies: HashMap>, -} - -impl<'ctx> CannotDeriveDefault<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type can derive - // default or not. - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>(&mut self, id: Id) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} into the cannot_derive_default set", id); - - let was_not_already_in_set = self.cannot_derive_default.insert(id); - assert!( - was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id - ); - - ConstrainResult::Changed - } - - fn is_not_default>(&self, id: Id) -> bool { - let id = id.into(); - self.cannot_derive_default.contains(&id) || - !self.ctx.whitelisted_items().contains(&id) - } -} - -impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashSet; - - fn new(ctx: &'ctx BindgenContext) -> CannotDeriveDefault<'ctx> { - let mut dependencies = HashMap::new(); - let cannot_derive_default = HashSet::new(); - - let whitelisted_items: HashSet<_> = - ctx.whitelisted_items().iter().cloned().collect(); - - let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items - .iter() - .cloned() - .flat_map(|i| { - let mut reachable = vec![i]; - i.trace(ctx, &mut |s, _| { reachable.push(s); }, &()); - reachable - }) - .collect(); - - for item in whitelisted_and_blacklisted_items { - dependencies.entry(item).or_insert(vec![]); - - { - // We reverse our natural IR graph edges to find dependencies - // between nodes. - item.trace( - ctx, - &mut |sub_item: ItemId, edge_kind| { - if ctx.whitelisted_items().contains(&sub_item) && - Self::consider_edge(edge_kind) - { - dependencies - .entry(sub_item) - .or_insert(vec![]) - .push(item); - } - }, - &(), - ); - } - } - - CannotDeriveDefault { - ctx, - cannot_derive_default, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if self.cannot_derive_default.contains(&id) { - trace!(" already know it cannot derive Default"); - return ConstrainResult::Same; - } - - if !self.ctx.whitelisted_items().contains(&id) { - trace!(" blacklisted items pessimistically cannot derive Default"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } - }; - - if item.is_opaque(self.ctx, &()) { - let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_default() - }); - return if layout_can_derive && - !(ty.is_union() && - self.ctx.options().rust_features().untagged_union) { - trace!(" we can trivially derive Default for the layout"); - ConstrainResult::Same - } else { - trace!(" we cannot derive Default for the layout"); - self.insert(id) - }; - } - - if ty.layout(self.ctx).map_or(false, |l| { - l.align > RUST_DERIVE_IN_ARRAY_LIMIT - }) - { - // We have to be conservative: the struct *could* have enough - // padding that we emit an array that is longer than - // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations - // into the IR and computed them before this analysis, then we could - // be precise rather than conservative here. - return self.insert(id); - } - - match *ty.kind() { - // Handle the simple cases. These can derive Default without further - // information. - TypeKind::Function(..) | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) => { - trace!(" simple type that can always derive Default"); - ConstrainResult::Same - } - - TypeKind::Void | - TypeKind::TypeParam | - TypeKind::Reference(..) | - TypeKind::NullPtr | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::ObjCInterface(..) | - TypeKind::Enum(..) => { - trace!(" types that always cannot derive Default"); - self.insert(id) - } - - TypeKind::Array(t, len) => { - if self.is_not_default(t) { - trace!( - " arrays of T for which we cannot derive Default \ - also cannot derive Default" - ); - return self.insert(id); - } - - if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!(" array is small enough to derive Default"); - ConstrainResult::Same - } else { - trace!(" array is too large to derive Default"); - self.insert(id) - } - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - if self.is_not_default(t) { - trace!( - " aliases and type refs to T which cannot derive \ - Default also cannot derive Default" - ); - self.insert(id) - } else { - trace!( - " aliases and type refs to T which can derive \ - Default can also derive Default" - ); - ConstrainResult::Same - } - } - - TypeKind::Comp(ref info) => { - assert!( - !info.has_non_type_template_params(), - "The early ty.is_opaque check should have handled this case" - ); - - if info.is_forward_declaration() { - trace!(" cannot derive Default for forward decls"); - return self.insert(id); - } - - if info.kind() == CompKind::Union { - if self.ctx.options().rust_features().untagged_union { - trace!(" cannot derive Default for Rust unions"); - return self.insert(id); - } - - if ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_default() - }) - { - trace!(" union layout can trivially derive Default"); - return ConstrainResult::Same; - } else { - trace!(" union layout cannot derive Default"); - return self.insert(id); - } - } - - if item.has_vtable(self.ctx) { - trace!(" comp with vtable cannot derive Default"); - return self.insert(id); - } - - let bases_cannot_derive = - info.base_members().iter().any(|base| { - !self.ctx.whitelisted_items().contains(&base.ty.into()) || - self.is_not_default(base.ty) - }); - if bases_cannot_derive { - trace!( - " base members cannot derive Default, so we can't \ - either" - ); - return self.insert(id); - } - - let fields_cannot_derive = - info.fields().iter().any(|f| match *f { - Field::DataMember(ref data) => { - !self.ctx.whitelisted_items().contains( - &data.ty().into(), - ) || - self.is_not_default(data.ty()) - } - Field::Bitfields(ref bfu) => { - if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " we cannot derive Default for a bitfield larger then \ - the limit" - ); - return true; - } - - bfu.bitfields().iter().any(|b| { - !self.ctx.whitelisted_items().contains( - &b.ty().into(), - ) || - self.is_not_default(b.ty()) - }) - } - }); - if fields_cannot_derive { - trace!( - " fields cannot derive Default, so we can't either" - ); - return self.insert(id); - } - - trace!(" comp can derive Default"); - ConstrainResult::Same - } - - TypeKind::TemplateInstantiation(ref template) => { - let args_cannot_derive = - template.template_arguments().iter().any(|arg| { - self.is_not_default(*arg) - }); - if args_cannot_derive { - trace!( - " template args cannot derive Default, so \ - insantiation can't either" - ); - return self.insert(id); - } - - assert!( - !template.template_definition().is_opaque(self.ctx, &()), - "The early ty.is_opaque check should have handled this case" - ); - let def_cannot_derive = - self.is_not_default(template.template_definition()); - if def_cannot_derive { - trace!( - " template definition cannot derive Default, so \ - insantiation can't either" - ); - return self.insert(id); - } - - trace!(" template instantiation can derive Default"); - ConstrainResult::Same - } - - TypeKind::Opaque => { - unreachable!( - "The early ty.is_opaque check should have handled this case" - ) - } - - TypeKind::UnresolvedTypeRef(..) => { - unreachable!( - "Type with unresolved type ref can't reach derive default" - ) - } - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashSet { - fn from(analysis: CannotDeriveDefault<'ctx>) -> Self { - analysis.cannot_derive_default - } -} diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs deleted file mode 100644 index c23a891e04..0000000000 --- a/src/ir/analysis/derive_hash.rs +++ /dev/null @@ -1,381 +0,0 @@ -//! Determining which types for which we can emit `#[derive(Hash)]`. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::CompKind; -use ir::comp::Field; -use ir::comp::FieldMethods; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::CanTriviallyDeriveHash; -use ir::item::IsOpaque; -use ir::traversal::EdgeKind; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; - -/// An analysis that finds for each IR item whether hash cannot be derived. -/// -/// We use the monotone constraint function `cannot_derive_hash`, defined as -/// follows: -/// -/// * If T is Opaque and layout of the type is known, get this layout as opaque -/// type and check whether it can be derived using trivial checks. -/// * If T is Array type, hash cannot be derived if the length of the array is -/// larger than the limit or the type of data the array contains cannot derive -/// hash. -/// * If T is a type alias, a templated alias or an indirection to another type, -/// hash cannot be derived if the type T refers to cannot be derived hash. -/// * If T is a compound type, hash cannot be derived if any of its base member -/// or field cannot be derived hash. -/// * If T is a pointer, T cannot be derived hash if T is a function pointer -/// and the function signature cannot be derived hash. -/// * If T is an instantiation of an abstract template definition, T cannot be -/// derived hash if any of the template arguments or template definition -/// cannot derive hash. -#[derive(Debug, Clone)] -pub struct CannotDeriveHash<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set cannot derive hash. - cannot_derive_hash: HashSet, - - // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_hash` set, then each of the ids in Vec need to be - // considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // can derive hash or not. - dependencies: HashMap>, -} - -impl<'ctx> CannotDeriveHash<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type can derive - // hash or not. - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>(&mut self, id: Id) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} into the cannot_derive_hash set", id); - - let was_not_already_in_set = self.cannot_derive_hash.insert(id); - assert!( - was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id - ); - - ConstrainResult::Changed - } -} - -impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashSet; - - fn new(ctx: &'ctx BindgenContext) -> CannotDeriveHash<'ctx> { - let cannot_derive_hash = HashSet::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - CannotDeriveHash { - ctx, - cannot_derive_hash, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if self.cannot_derive_hash.contains(&id) { - trace!(" already know it cannot derive Hash"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } - }; - - if self.ctx.no_hash_by_name(&item) { - return self.insert(id) - } - - if item.is_opaque(self.ctx, &()) { - let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_hash() - }); - return if layout_can_derive && - !(ty.is_union() && - self.ctx.options().rust_features().untagged_union) { - trace!(" we can trivially derive Hash for the layout"); - ConstrainResult::Same - } else { - trace!(" we cannot derive Hash for the layout"); - self.insert(id) - }; - } - - if ty.layout(self.ctx).map_or(false, |l| { - l.align > RUST_DERIVE_IN_ARRAY_LIMIT - }) - { - // We have to be conservative: the struct *could* have enough - // padding that we emit an array that is longer than - // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations - // into the IR and computed them before this analysis, then we could - // be precise rather than conservative here. - return self.insert(id); - } - - match *ty.kind() { - // Handle the simple cases. These can derive hash without further - // information. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Enum(..) | - TypeKind::TypeParam | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::BlockPointer | - TypeKind::Reference(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!(" simple type that can always derive Hash"); - ConstrainResult::Same - } - - TypeKind::Complex(..) | - TypeKind::Float(..) => { - trace!(" float cannot derive Hash"); - self.insert(id) - } - - TypeKind::Array(t, len) => { - if self.cannot_derive_hash.contains(&t.into()) { - trace!( - " arrays of T for which we cannot derive Hash \ - also cannot derive Hash" - ); - return self.insert(id); - } - - if len == 0 { - trace!(" cannot derive `Hash` for incomplete arrays"); - self.insert(id) - } else if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!(" array is small enough to derive Hash"); - ConstrainResult::Same - } else { - trace!(" array is too large to derive Hash"); - self.insert(id) - } - } - - TypeKind::Pointer(inner) => { - let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); - if let TypeKind::Function(ref sig) = *inner_type.kind() { - if !sig.can_trivially_derive_hash() { - trace!( - " function pointer that can't trivially derive Hash" - ); - return self.insert(id); - } - } - trace!(" pointers can derive Hash"); - ConstrainResult::Same - } - - TypeKind::Function(ref sig) => { - if !sig.can_trivially_derive_hash() { - trace!(" function that can't trivially derive Hash"); - return self.insert(id); - } - trace!(" function can derive Hash"); - ConstrainResult::Same - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - if self.cannot_derive_hash.contains(&t.into()) { - trace!( - " aliases and type refs to T which cannot derive \ - Hash also cannot derive Hash" - ); - self.insert(id) - } else { - trace!( - " aliases and type refs to T which can derive \ - Hash can also derive Hash" - ); - ConstrainResult::Same - } - } - - TypeKind::Comp(ref info) => { - assert!( - !info.has_non_type_template_params(), - "The early ty.is_opaque check should have handled this case" - ); - - if info.is_forward_declaration() { - trace!(" cannot derive Hash for forward decls"); - return self.insert(id); - } - - if info.kind() == CompKind::Union { - if self.ctx.options().rust_features().untagged_union { - trace!(" cannot derive Hash for Rust unions"); - return self.insert(id); - } - - if ty.layout(self.ctx).map_or(true, |l| { - l.opaque().can_trivially_derive_hash() - }) - { - trace!(" union layout can trivially derive Hash"); - return ConstrainResult::Same; - } else { - trace!(" union layout cannot derive Hash"); - return self.insert(id); - } - } - - let bases_cannot_derive = - info.base_members().iter().any(|base| { - !self.ctx.whitelisted_items().contains(&base.ty.into()) || - self.cannot_derive_hash.contains(&base.ty.into()) - }); - if bases_cannot_derive { - trace!( - " base members cannot derive Hash, so we can't \ - either" - ); - return self.insert(id); - } - - let fields_cannot_derive = - info.fields().iter().any(|f| match *f { - Field::DataMember(ref data) => { - !self.ctx.whitelisted_items().contains( - &data.ty().into(), - ) || - self.cannot_derive_hash.contains(&data.ty().into()) - } - Field::Bitfields(ref bfu) => { - if bfu.layout().align > RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " we cannot derive Hash for a bitfield larger then \ - the limit" - ); - return true; - } - - bfu.bitfields().iter().any(|b| { - !self.ctx.whitelisted_items().contains( - &b.ty().into(), - ) || - self.cannot_derive_hash.contains(&b.ty().into()) - }) - } - }); - if fields_cannot_derive { - trace!(" fields cannot derive Hash, so we can't either"); - return self.insert(id); - } - - trace!(" comp can derive Hash"); - ConstrainResult::Same - } - - TypeKind::TemplateInstantiation(ref template) => { - let args_cannot_derive = - template.template_arguments().iter().any(|arg| { - self.cannot_derive_hash.contains(&arg.into()) - }); - if args_cannot_derive { - trace!( - " template args cannot derive Hash, so \ - insantiation can't either" - ); - return self.insert(id); - } - - assert!( - !template.template_definition().is_opaque(self.ctx, &()), - "The early ty.is_opaque check should have handled this case" - ); - let def_cannot_derive = self.cannot_derive_hash.contains( - &template.template_definition().into(), - ); - if def_cannot_derive { - trace!( - " template definition cannot derive Hash, so \ - insantiation can't either" - ); - return self.insert(id); - } - - trace!(" template instantiation can derive Hash"); - ConstrainResult::Same - } - - TypeKind::Opaque => { - unreachable!( - "The early ty.is_opaque check should have handled this case" - ) - } - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashSet { - fn from(analysis: CannotDeriveHash<'ctx>) -> Self { - analysis.cannot_derive_hash - } -} diff --git a/src/ir/analysis/derive_partialeq_or_partialord.rs b/src/ir/analysis/derive_partialeq_or_partialord.rs deleted file mode 100644 index cebdceefe4..0000000000 --- a/src/ir/analysis/derive_partialeq_or_partialord.rs +++ /dev/null @@ -1,414 +0,0 @@ -//! Determining which types for which we cannot emit `#[derive(PartialEq, -//! PartialOrd)]`. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::CompKind; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::{CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; -use ir::item::{Item, IsOpaque}; -use ir::traversal::{EdgeKind, Trace}; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::{TypeKind, Type}; -use std::collections::HashMap; -use std::collections::hash_map::Entry; - -/// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd` -/// cannot be derived. -/// -/// We use the monotone constraint function -/// `cannot_derive_partialeq_or_partialord`, defined as follows: -/// -/// * If T is Opaque and layout of the type is known, get this layout as opaque -/// type and check whether it can be derived using trivial checks. -/// -/// * If T is Array type, `PartialEq` or partialord cannot be derived if the array is incomplete, if the length of -/// the array is larger than the limit, or the type of data the array contains cannot derive -/// `PartialEq`/`PartialOrd`. -/// -/// * If T is a type alias, a templated alias or an indirection to another type, -/// `PartialEq`/`PartialOrd` cannot be derived if the type T refers to cannot be -/// derived `PartialEq`/`PartialOrd`. -/// -/// * If T is a compound type, `PartialEq`/`PartialOrd` cannot be derived if any -/// of its base member or field cannot be derived `PartialEq`/`PartialOrd`. -/// -/// * If T is a pointer, T cannot be derived `PartialEq`/`PartialOrd` if T is a -/// function pointer and the function signature cannot be derived -/// `PartialEq`/`PartialOrd`. -/// -/// * If T is an instantiation of an abstract template definition, T cannot be -/// derived `PartialEq`/`PartialOrd` if any of the template arguments or -/// template definition cannot derive `PartialEq`/`PartialOrd`. -#[derive(Debug, Clone)] -pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. - // Contains information whether particular item can derive `PartialEq`/`PartialOrd`. - can_derive_partialeq_or_partialord: HashMap, - - // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_partialeq_or_partialord` set, then each of the ids - // in Vec need to be considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // can derive `PartialEq`/`PartialOrd`. - dependencies: HashMap>, -} - -impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type can derive - // `PartialEq`/`PartialOrd`. - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>( - &mut self, - id: Id, - can_derive: CanDerive, - ) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} can_derive={:?}", id, can_derive); - - if let CanDerive::Yes = can_derive { - return ConstrainResult::Same; - } - - match self.can_derive_partialeq_or_partialord.entry(id) { - Entry::Occupied(mut entry) => if *entry.get() < can_derive { - entry.insert(can_derive); - ConstrainResult::Changed - } else { - ConstrainResult::Same - }, - Entry::Vacant(entry) => { - entry.insert(can_derive); - ConstrainResult::Changed - } - } - } - - fn constrain_type(&mut self, item: &Item, ty: &Type) -> CanDerive { - if !self.ctx.whitelisted_items().contains(&item.id()) { - return CanDerive::No; - } - - if self.ctx.no_partialeq_by_name(&item) { - return CanDerive::No; - } - - trace!("ty: {:?}", ty); - if item.is_opaque(self.ctx, &()) { - if ty.is_union() - && self.ctx.options().rust_features().untagged_union - { - trace!( - " cannot derive `PartialEq`/`PartialOrd` for Rust unions" - ); - return CanDerive::No; - } - - let layout_can_derive = ty.layout(self.ctx) - .map_or(CanDerive::Yes, |l| { - l.opaque().can_trivially_derive_partialeq_or_partialord() - }); - - match layout_can_derive { - CanDerive::Yes => { - trace!( - " we can trivially derive `PartialEq`/`PartialOrd` for the layout" - ); - } - _ => { - trace!( - " we cannot derive `PartialEq`/`PartialOrd` for the layout" - ); - } - }; - return layout_can_derive; - } - - match *ty.kind() { - // Handle the simple cases. These can derive partialeq without further - // information. - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Complex(..) | - TypeKind::Float(..) | - TypeKind::Enum(..) | - TypeKind::TypeParam | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::BlockPointer | - TypeKind::Reference(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!( - " simple type that can always derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::Yes; - } - - TypeKind::Array(t, len) => { - let inner_type = self.can_derive_partialeq_or_partialord - .get(&t.into()) - .cloned() - .unwrap_or(CanDerive::Yes); - if inner_type != CanDerive::Yes { - trace!( - " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \ - also cannot derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::No; - } - - if len == 0 { - trace!( - " cannot derive `PartialEq`/`PartialOrd` for incomplete arrays" - ); - return CanDerive::No; - } else if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " array is small enough to derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::Yes; - } else { - trace!( - " array is too large to derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::ArrayTooLarge; - } - } - - TypeKind::Pointer(inner) => { - let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); - if let TypeKind::Function(ref sig) = *inner_type.kind() { - if sig.can_trivially_derive_partialeq_or_partialord() - != CanDerive::Yes - { - trace!( - " function pointer that can't trivially derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::No; - } - } - trace!(" pointers can derive `PartialEq`/`PartialOrd`"); - return CanDerive::Yes; - } - - TypeKind::Function(ref sig) => { - if sig.can_trivially_derive_partialeq_or_partialord() - != CanDerive::Yes - { - trace!( - " function that can't trivially derive `PartialEq`/`PartialOrd`" - ); - return CanDerive::No; - } - trace!(" function can derive `PartialEq`/`PartialOrd`"); - return CanDerive::Yes; - } - - TypeKind::Comp(ref info) => { - assert!( - !info.has_non_type_template_params(), - "The early ty.is_opaque check should have handled this case" - ); - - if info.is_forward_declaration() { - trace!(" cannot derive for forward decls"); - return CanDerive::No; - } - - if info.kind() == CompKind::Union { - if self.ctx.options().rust_features().untagged_union { - trace!( - " cannot derive `PartialEq`/`PartialOrd` for Rust unions" - ); - return CanDerive::No; - } - - let layout_can_derive = - ty.layout(self.ctx).map_or(CanDerive::Yes, |l| { - l.opaque() - .can_trivially_derive_partialeq_or_partialord() - }); - match layout_can_derive { - CanDerive::Yes => { - trace!( - " union layout can trivially derive `PartialEq`/`PartialOrd`" - ); - } - _ => { - trace!( - " union layout cannot derive `PartialEq`/`PartialOrd`" - ); - } - }; - return layout_can_derive; - } - return self.constrain_join(item); - } - - TypeKind::ResolvedTypeRef(..) | - TypeKind::TemplateAlias(..) | - TypeKind::Alias(..) | - TypeKind::TemplateInstantiation(..) => { - return self.constrain_join(item); - } - - TypeKind::Opaque => unreachable!( - "The early ty.is_opaque check should have handled this case" - ), - } - } - - fn constrain_join(&mut self, item: &Item) -> CanDerive { - let mut candidate = CanDerive::Yes; - - item.trace( - self.ctx, - &mut |sub_id, edge_kind| { - // Ignore ourselves, since union with ourself is a - // no-op. Ignore edges that aren't relevant to the - // analysis. - if sub_id == item.id() || !Self::consider_edge(edge_kind) { - return; - } - - let can_derive = self.can_derive_partialeq_or_partialord - .get(&sub_id) - .cloned() - .unwrap_or_default(); - - candidate |= can_derive; - }, - &(), - ); - - candidate - } -} - -impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashMap; - - fn new( - ctx: &'ctx BindgenContext, - ) -> CannotDerivePartialEqOrPartialOrd<'ctx> { - let can_derive_partialeq_or_partialord = HashMap::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - CannotDerivePartialEqOrPartialOrd { - ctx, - can_derive_partialeq_or_partialord, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - // The transitive closure of all whitelisted items, including explicitly - // blacklisted items. - self.ctx - .whitelisted_items() - .iter() - .cloned() - .flat_map(|i| { - let mut reachable = vec![i]; - i.trace( - self.ctx, - &mut |s, _| { - reachable.push(s); - }, - &(), - ); - reachable - }) - .collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if let Some(CanDerive::No) = - self.can_derive_partialeq_or_partialord.get(&id).cloned() - { - trace!( - " already know it cannot derive `PartialEq`/`PartialOrd`" - ); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let can_derive = match item.as_type() { - Some(ty) => { - let mut can_derive = self.constrain_type(item, ty); - if let CanDerive::Yes = can_derive { - if ty.layout(self.ctx) - .map_or(false, |l| l.align > RUST_DERIVE_IN_ARRAY_LIMIT) - { - // We have to be conservative: the struct *could* have enough - // padding that we emit an array that is longer than - // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations - // into the IR and computed them before this analysis, then we could - // be precise rather than conservative here. - can_derive = CanDerive::ArrayTooLarge; - } - } - can_derive - } - None => self.constrain_join(item), - }; - - self.insert(id, can_derive) - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> - for HashMap { - fn from(analysis: CannotDerivePartialEqOrPartialOrd<'ctx>) -> Self { - extra_assert!( - analysis - .can_derive_partialeq_or_partialord - .values() - .all(|v| { *v != CanDerive::Yes }) - ); - - analysis.can_derive_partialeq_or_partialord - } -} diff --git a/src/ir/analysis/has_float.rs b/src/ir/analysis/has_float.rs deleted file mode 100644 index 193862c0b9..0000000000 --- a/src/ir/analysis/has_float.rs +++ /dev/null @@ -1,238 +0,0 @@ -//! Determining which types has float. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use std::collections::HashSet; -use std::collections::HashMap; -use ir::context::{BindgenContext, ItemId}; -use ir::traversal::EdgeKind; -use ir::ty::TypeKind; -use ir::comp::Field; -use ir::comp::FieldMethods; - -/// An analysis that finds for each IR item whether it has float or not. -/// -/// We use the monotone constraint function `has_float`, -/// defined as follows: -/// -/// * If T is float or complex float, T trivially has. -/// * If T is a type alias, a templated alias or an indirection to another type, -/// it has float if the type T refers to has. -/// * If T is a compound type, it has float if any of base memter or field -/// has. -/// * If T is an instantiation of an abstract template definition, T has -/// float if any of the template arguments or template definition -/// has. -#[derive(Debug, Clone)] -pub struct HasFloat<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set has float. - has_float: HashSet, - - // Dependencies saying that if a key ItemId has been inserted into the - // `has_float` set, then each of the ids in Vec need to be - // considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // has float or not. - dependencies: HashMap>, -} - -impl<'ctx> HasFloat<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TypeReference | - EdgeKind::VarType | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => true, - - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::InnerType | - EdgeKind::InnerVar | - EdgeKind::Method => false, - EdgeKind::Generic => false, - } - } - - fn insert>(&mut self, id: Id) -> ConstrainResult { - let id = id.into(); - trace!("inserting {:?} into the has_float set", id); - - let was_not_already_in_set = self.has_float.insert(id); - assert!( - was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id - ); - - ConstrainResult::Changed - } -} - -impl<'ctx> MonotoneFramework for HasFloat<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashSet; - - fn new(ctx: &'ctx BindgenContext) -> HasFloat<'ctx> { - let has_float = HashSet::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - HasFloat { - ctx, - has_float, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if self.has_float.contains(&id) { - trace!(" already know it do not have float"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } - }; - - match *ty.kind() { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::BlockPointer | - TypeKind::TypeParam | - TypeKind::Opaque | - TypeKind::Pointer(..) | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!(" simple type that do not have float"); - ConstrainResult::Same - } - - TypeKind::Float(..) | - TypeKind::Complex(..) => { - trace!(" float type has float"); - self.insert(id) - } - - TypeKind::Array(t, _) => { - if self.has_float.contains(&t.into()) { - trace!(" Array with type T that has float also has float"); - return self.insert(id) - } - trace!(" Array with type T that do not have float also do not have float"); - ConstrainResult::Same - } - - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { - if self.has_float.contains(&t.into()) { - trace!(" aliases and type refs to T which have float \ - also have float"); - self.insert(id) - } else { - trace!(" aliases and type refs to T which do not have float \ - also do not have floaarrayt"); - ConstrainResult::Same - } - } - - TypeKind::Comp(ref info) => { - let bases_have = info.base_members() - .iter() - .any(|base| self.has_float.contains(&base.ty.into())); - if bases_have { - trace!(" bases have float, so we also have"); - return self.insert(id); - } - let fields_have = info.fields() - .iter() - .any(|f| { - match *f { - Field::DataMember(ref data) => { - self.has_float.contains(&data.ty().into()) - } - Field::Bitfields(ref bfu) => { - bfu.bitfields() - .iter().any(|b| { - self.has_float.contains(&b.ty().into()) - }) - }, - } - }); - if fields_have { - trace!(" fields have float, so we also have"); - return self.insert(id); - } - - trace!(" comp doesn't have float"); - ConstrainResult::Same - } - - TypeKind::TemplateInstantiation(ref template) => { - let args_have = template.template_arguments() - .iter() - .any(|arg| self.has_float.contains(&arg.into())); - if args_have { - trace!(" template args have float, so \ - insantiation also has float"); - return self.insert(id); - } - - let def_has = self.has_float - .contains(&template.template_definition().into()); - if def_has { - trace!(" template definition has float, so \ - insantiation also has"); - return self.insert(id); - } - - trace!(" template instantiation do not have float"); - ConstrainResult::Same - } - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashSet { - fn from(analysis: HasFloat<'ctx>) -> Self { - analysis.has_float - } -} diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs deleted file mode 100644 index f3f2a69534..0000000000 --- a/src/ir/analysis/has_vtable.rs +++ /dev/null @@ -1,249 +0,0 @@ -//! Determining which types has vtable - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::context::{BindgenContext, ItemId}; -use ir::traversal::EdgeKind; -use ir::ty::TypeKind; -use std::cmp; -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::ops; - -/// The result of the `HasVtableAnalysis` for an individual item. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord)] -pub enum HasVtableResult { - /// The item has a vtable, but the actual vtable pointer is in a base - /// member. - BaseHasVtable, - - /// The item has a vtable and the actual vtable pointer is within this item. - SelfHasVtable, - - /// The item does not have a vtable pointer. - No -} - -impl Default for HasVtableResult { - fn default() -> Self { - HasVtableResult::No - } -} - -impl cmp::PartialOrd for HasVtableResult { - fn partial_cmp(&self, rhs: &Self) -> Option { - use self::HasVtableResult::*; - - match (*self, *rhs) { - (x, y) if x == y => Some(cmp::Ordering::Equal), - (BaseHasVtable, _) => Some(cmp::Ordering::Greater), - (_, BaseHasVtable) => Some(cmp::Ordering::Less), - (SelfHasVtable, _) => Some(cmp::Ordering::Greater), - (_, SelfHasVtable) => Some(cmp::Ordering::Less), - _ => unreachable!(), - } - } -} - -impl HasVtableResult { - /// Take the least upper bound of `self` and `rhs`. - pub fn join(self, rhs: Self) -> Self { - cmp::max(self, rhs) - } -} - -impl ops::BitOr for HasVtableResult { - type Output = Self; - - fn bitor(self, rhs: HasVtableResult) -> Self::Output { - self.join(rhs) - } -} - -impl ops::BitOrAssign for HasVtableResult { - fn bitor_assign(&mut self, rhs: HasVtableResult) { - *self = self.join(rhs) - } -} - -/// An analysis that finds for each IR item whether it has vtable or not -/// -/// We use the monotone function `has vtable`, defined as follows: -/// -/// * If T is a type alias, a templated alias, an indirection to another type, -/// or a reference of a type, T has vtable if the type T refers to has vtable. -/// * If T is a compound type, T has vtable if we saw a virtual function when -/// parsing it or any of its base member has vtable. -/// * If T is an instantiation of an abstract template definition, T has -/// vtable if template definition has vtable -#[derive(Debug, Clone)] -pub struct HasVtableAnalysis<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set definitely has a vtable. - have_vtable: HashMap, - - // Dependencies saying that if a key ItemId has been inserted into the - // `have_vtable` set, then each of the ids in Vec need to be - // considered again. - // - // This is a subset of the natural IR graph with reversed edges, where we - // only include the edges from the IR graph that can affect whether a type - // has a vtable or not. - dependencies: HashMap>, -} - -impl<'ctx> HasVtableAnalysis<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type has a - // vtable or not. - EdgeKind::TypeReference | - EdgeKind::BaseMember | - EdgeKind::TemplateDeclaration => true, - _ => false, - } - } - - fn insert>(&mut self, id: Id, result: HasVtableResult) -> ConstrainResult { - if let HasVtableResult::No = result { - return ConstrainResult::Same; - } - - let id = id.into(); - match self.have_vtable.entry(id) { - Entry::Occupied(mut entry) => { - if *entry.get() < result { - entry.insert(result); - ConstrainResult::Changed - } else { - ConstrainResult::Same - } - } - Entry::Vacant(entry) => { - entry.insert(result); - ConstrainResult::Changed - } - } - } - - fn forward(&mut self, from: Id1, to: Id2) -> ConstrainResult - where - Id1: Into, - Id2: Into, - { - let from = from.into(); - let to = to.into(); - - match self.have_vtable.get(&from).cloned() { - None => ConstrainResult::Same, - Some(r) => self.insert(to, r), - } - } -} - -impl<'ctx> MonotoneFramework for HasVtableAnalysis<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashMap; - - fn new(ctx: &'ctx BindgenContext) -> HasVtableAnalysis<'ctx> { - let have_vtable = HashMap::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - HasVtableAnalysis { - ctx, - have_vtable, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain {:?}", id); - - let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - None => return ConstrainResult::Same, - Some(ty) => ty, - }; - - // TODO #851: figure out a way to handle deriving from template type parameters. - match *ty.kind() { - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) | - TypeKind::ResolvedTypeRef(t) | - TypeKind::Reference(t) => { - trace!(" aliases and references forward to their inner type"); - self.forward(t, id) - } - - TypeKind::Comp(ref info) => { - trace!(" comp considers its own methods and bases"); - let mut result = HasVtableResult::No; - - if info.has_own_virtual_method() { - trace!(" comp has its own virtual method"); - result |= HasVtableResult::SelfHasVtable; - } - - let bases_has_vtable = info.base_members().iter().any(|base| { - trace!(" comp has a base with a vtable: {:?}", base); - self.have_vtable.contains_key(&base.ty.into()) - }); - if bases_has_vtable { - result |= HasVtableResult::BaseHasVtable; - } - - self.insert(id, result) - } - - TypeKind::TemplateInstantiation(ref inst) => { - self.forward(inst.template_definition(), id) - } - - _ => ConstrainResult::Same, - } - } - - fn each_depending_on(&self, id: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&id) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> for HashMap { - fn from(analysis: HasVtableAnalysis<'ctx>) -> Self { - // We let the lack of an entry mean "No" to save space. - extra_assert!(analysis.have_vtable.values().all(|v| { - *v != HasVtableResult::No - })); - - analysis.have_vtable - } -} - -/// A convenience trait for the things for which we might wonder if they have a -/// vtable during codegen. -/// -/// This is not for _computing_ whether the thing has a vtable, it is for -/// looking up the results of the HasVtableAnalysis's computations for a -/// specific thing. -pub trait HasVtable { - /// Return `true` if this thing has vtable, `false` otherwise. - fn has_vtable(&self, ctx: &BindgenContext) -> bool; - - /// Return `true` if this thing has an actual vtable pointer in itself, as - /// opposed to transitively in a base member. - fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool; -} diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs deleted file mode 100644 index 64958c07c1..0000000000 --- a/src/ir/analysis/mod.rs +++ /dev/null @@ -1,402 +0,0 @@ -//! Fix-point analyses on the IR using the "monotone framework". -//! -//! A lattice is a set with a partial ordering between elements, where there is -//! a single least upper bound and a single greatest least bound for every -//! subset. We are dealing with finite lattices, which means that it has a -//! finite number of elements, and it follows that there exists a single top and -//! a single bottom member of the lattice. For example, the power set of a -//! finite set forms a finite lattice where partial ordering is defined by set -//! inclusion, that is `a <= b` if `a` is a subset of `b`. Here is the finite -//! lattice constructed from the set {0,1,2}: -//! -//! ```text -//! .----- Top = {0,1,2} -----. -//! / | \ -//! / | \ -//! / | \ -//! {0,1} -------. {0,2} .--------- {1,2} -//! | \ / \ / | -//! | / \ | -//! | / \ / \ | -//! {0} --------' {1} `---------- {2} -//! \ | / -//! \ | / -//! \ | / -//! `------ Bottom = {} ------' -//! ``` -//! -//! A monotone function `f` is a function where if `x <= y`, then it holds that -//! `f(x) <= f(y)`. It should be clear that running a monotone function to a -//! fix-point on a finite lattice will always terminate: `f` can only "move" -//! along the lattice in a single direction, and therefore can only either find -//! a fix-point in the middle of the lattice or continue to the top or bottom -//! depending if it is ascending or descending the lattice respectively. -//! -//! For a deeper introduction to the general form of this kind of analysis, see -//! [Static Program Analysis by Anders Møller and Michael I. Schwartzbach][spa]. -//! -//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf - -// Re-export individual analyses. -mod template_params; -pub use self::template_params::UsedTemplateParameters; -mod derive_debug; -pub use self::derive_debug::CannotDeriveDebug; -mod has_vtable; -pub use self::has_vtable::{HasVtable, HasVtableAnalysis, HasVtableResult}; -mod has_destructor; -pub use self::has_destructor::HasDestructorAnalysis; -mod derive_default; -pub use self::derive_default::CannotDeriveDefault; -mod derive_copy; -pub use self::derive_copy::CannotDeriveCopy; -mod has_type_param_in_array; -pub use self::has_type_param_in_array::HasTypeParameterInArray; -mod derive_hash; -pub use self::derive_hash::CannotDeriveHash; -mod derive_partialeq_or_partialord; -pub use self::derive_partialeq_or_partialord::CannotDerivePartialEqOrPartialOrd; -mod has_float; -pub use self::has_float::HasFloat; -mod sizedness; -pub use self::sizedness::{Sizedness, SizednessAnalysis, SizednessResult}; - -use ir::context::{BindgenContext, ItemId}; - -use ir::traversal::{EdgeKind, Trace}; -use std::collections::HashMap; -use std::fmt; -use std::ops; - -/// An analysis in the monotone framework. -/// -/// Implementors of this trait must maintain the following two invariants: -/// -/// 1. The concrete data must be a member of a finite-height lattice. -/// 2. The concrete `constrain` method must be monotone: that is, -/// if `x <= y`, then `constrain(x) <= constrain(y)`. -/// -/// If these invariants do not hold, iteration to a fix-point might never -/// complete. -/// -/// For a simple example analysis, see the `ReachableFrom` type in the `tests` -/// module below. -pub trait MonotoneFramework: Sized + fmt::Debug { - /// The type of node in our dependency graph. - /// - /// This is just generic (and not `ItemId`) so that we can easily unit test - /// without constructing real `Item`s and their `ItemId`s. - type Node: Copy; - - /// Any extra data that is needed during computation. - /// - /// Again, this is just generic (and not `&BindgenContext`) so that we can - /// easily unit test without constructing real `BindgenContext`s full of - /// real `Item`s and real `ItemId`s. - type Extra: Sized; - - /// The final output of this analysis. Once we have reached a fix-point, we - /// convert `self` into this type, and return it as the final result of the - /// analysis. - type Output: From + fmt::Debug; - - /// Construct a new instance of this analysis. - fn new(extra: Self::Extra) -> Self; - - /// Get the initial set of nodes from which to start the analysis. Unless - /// you are sure of some domain-specific knowledge, this should be the - /// complete set of nodes. - fn initial_worklist(&self) -> Vec; - - /// Update the analysis for the given node. - /// - /// If this results in changing our internal state (ie, we discovered that - /// we have not reached a fix-point and iteration should continue), return - /// `ConstrainResult::Changed`. Otherwise, return `ConstrainResult::Same`. - /// When `constrain` returns `ConstrainResult::Same` for all nodes in the - /// set, we have reached a fix-point and the analysis is complete. - fn constrain(&mut self, node: Self::Node) -> ConstrainResult; - - /// For each node `d` that depends on the given `node`'s current answer when - /// running `constrain(d)`, call `f(d)`. This informs us which new nodes to - /// queue up in the worklist when `constrain(node)` reports updated - /// information. - fn each_depending_on(&self, node: Self::Node, f: F) - where - F: FnMut(Self::Node); -} - -/// Whether an analysis's `constrain` function modified the incremental results -/// or not. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ConstrainResult { - /// The incremental results were updated, and the fix-point computation - /// should continue. - Changed, - - /// The incremental results were not updated. - Same, -} - -impl Default for ConstrainResult { - fn default() -> Self { - ConstrainResult::Same - } -} - -impl ops::BitOr for ConstrainResult { - type Output = Self; - - fn bitor(self, rhs: ConstrainResult) -> Self::Output { - if self == ConstrainResult::Changed || rhs == ConstrainResult::Changed { - ConstrainResult::Changed - } else { - ConstrainResult::Same - } - } -} - -impl ops::BitOrAssign for ConstrainResult { - fn bitor_assign(&mut self, rhs: ConstrainResult) { - *self = *self | rhs; - } -} - -/// Run an analysis in the monotone framework. -pub fn analyze(extra: Analysis::Extra) -> Analysis::Output -where - Analysis: MonotoneFramework, -{ - let mut analysis = Analysis::new(extra); - let mut worklist = analysis.initial_worklist(); - - while let Some(node) = worklist.pop() { - if let ConstrainResult::Changed = analysis.constrain(node) { - analysis.each_depending_on( - node, - |needs_work| { worklist.push(needs_work); }, - ); - } - } - - analysis.into() -} - -/// Generate the dependency map for analysis -pub fn generate_dependencies( - ctx: &BindgenContext, - consider_edge: F, -) -> HashMap> -where - F: Fn(EdgeKind) -> bool, -{ - let mut dependencies = HashMap::new(); - - for &item in ctx.whitelisted_items() { - dependencies.entry(item).or_insert(vec![]); - - { - // We reverse our natural IR graph edges to find dependencies - // between nodes. - item.trace( - ctx, - &mut |sub_item: ItemId, edge_kind| { - if ctx.whitelisted_items().contains(&sub_item) && - consider_edge(edge_kind) - { - dependencies.entry(sub_item).or_insert(vec![]).push( - item, - ); - } - }, - &(), - ); - } - } - dependencies -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::{HashMap, HashSet}; - - // Here we find the set of nodes that are reachable from any given - // node. This is a lattice mapping nodes to subsets of all nodes. Our join - // function is set union. - // - // This is our test graph: - // - // +---+ +---+ - // | | | | - // | 1 | .----| 2 | - // | | | | | - // +---+ | +---+ - // | | ^ - // | | | - // | +---+ '------' - // '----->| | - // | 3 | - // .------| |------. - // | +---+ | - // | ^ | - // v | v - // +---+ | +---+ +---+ - // | | | | | | | - // | 4 | | | 5 |--->| 6 | - // | | | | | | | - // +---+ | +---+ +---+ - // | | | | - // | | | v - // | +---+ | +---+ - // | | | | | | - // '----->| 7 |<-----' | 8 | - // | | | | - // +---+ +---+ - // - // And here is the mapping from a node to the set of nodes that are - // reachable from it within the test graph: - // - // 1: {3,4,5,6,7,8} - // 2: {2} - // 3: {3,4,5,6,7,8} - // 4: {3,4,5,6,7,8} - // 5: {3,4,5,6,7,8} - // 6: {8} - // 7: {3,4,5,6,7,8} - // 8: {} - - #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] - struct Node(usize); - - #[derive(Clone, Debug, Default, PartialEq, Eq)] - struct Graph(HashMap>); - - impl Graph { - fn make_test_graph() -> Graph { - let mut g = Graph::default(); - g.0.insert(Node(1), vec![Node(3)]); - g.0.insert(Node(2), vec![Node(2)]); - g.0.insert(Node(3), vec![Node(4), Node(5)]); - g.0.insert(Node(4), vec![Node(7)]); - g.0.insert(Node(5), vec![Node(6), Node(7)]); - g.0.insert(Node(6), vec![Node(8)]); - g.0.insert(Node(7), vec![Node(3)]); - g.0.insert(Node(8), vec![]); - g - } - - fn reverse(&self) -> Graph { - let mut reversed = Graph::default(); - for (node, edges) in self.0.iter() { - reversed.0.entry(*node).or_insert(vec![]); - for referent in edges.iter() { - reversed.0.entry(*referent).or_insert(vec![]).push(*node); - } - } - reversed - } - } - - #[derive(Clone, Debug, PartialEq, Eq)] - struct ReachableFrom<'a> { - reachable: HashMap>, - graph: &'a Graph, - reversed: Graph, - } - - impl<'a> MonotoneFramework for ReachableFrom<'a> { - type Node = Node; - type Extra = &'a Graph; - type Output = HashMap>; - - fn new(graph: &'a Graph) -> ReachableFrom { - let reversed = graph.reverse(); - ReachableFrom { - reachable: Default::default(), - graph: graph, - reversed: reversed, - } - } - - fn initial_worklist(&self) -> Vec { - self.graph.0.keys().cloned().collect() - } - - fn constrain(&mut self, node: Node) -> ConstrainResult { - // The set of nodes reachable from a node `x` is - // - // reachable(x) = s_0 U s_1 U ... U reachable(s_0) U reachable(s_1) U ... - // - // where there exist edges from `x` to each of `s_0, s_1, ...`. - // - // Yes, what follows is a **terribly** inefficient set union - // implementation. Don't copy this code outside of this test! - - let original_size = - self.reachable.entry(node).or_insert(HashSet::new()).len(); - - for sub_node in self.graph.0[&node].iter() { - self.reachable.get_mut(&node).unwrap().insert(*sub_node); - - let sub_reachable = self.reachable - .entry(*sub_node) - .or_insert(HashSet::new()) - .clone(); - - for transitive in sub_reachable { - self.reachable.get_mut(&node).unwrap().insert(transitive); - } - } - - let new_size = self.reachable[&node].len(); - if original_size != new_size { - ConstrainResult::Changed - } else { - ConstrainResult::Same - } - } - - fn each_depending_on(&self, node: Node, mut f: F) - where - F: FnMut(Node), - { - for dep in self.reversed.0[&node].iter() { - f(*dep); - } - } - } - - impl<'a> From> for HashMap> { - fn from(reachable: ReachableFrom<'a>) -> Self { - reachable.reachable - } - } - - #[test] - fn monotone() { - let g = Graph::make_test_graph(); - let reachable = analyze::(&g); - println!("reachable = {:#?}", reachable); - - fn nodes
(nodes: A) -> HashSet - where - A: AsRef<[usize]>, - { - nodes.as_ref().iter().cloned().map(Node).collect() - } - - let mut expected = HashMap::new(); - expected.insert(Node(1), nodes([3, 4, 5, 6, 7, 8])); - expected.insert(Node(2), nodes([2])); - expected.insert(Node(3), nodes([3, 4, 5, 6, 7, 8])); - expected.insert(Node(4), nodes([3, 4, 5, 6, 7, 8])); - expected.insert(Node(5), nodes([3, 4, 5, 6, 7, 8])); - expected.insert(Node(6), nodes([8])); - expected.insert(Node(7), nodes([3, 4, 5, 6, 7, 8])); - expected.insert(Node(8), nodes([])); - println!("expected = {:#?}", expected); - - assert_eq!(reachable, expected); - } -} diff --git a/src/ir/analysis/sizedness.rs b/src/ir/analysis/sizedness.rs deleted file mode 100644 index e82c1798e1..0000000000 --- a/src/ir/analysis/sizedness.rs +++ /dev/null @@ -1,360 +0,0 @@ -//! Determining the sizedness of types (as base classes and otherwise). - -use super::{ConstrainResult, MonotoneFramework, HasVtable, generate_dependencies}; -use ir::context::{BindgenContext, TypeId}; -use ir::item::IsOpaque; -use ir::traversal::EdgeKind; -use ir::ty::TypeKind; -use std::cmp; -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::ops; - -/// The result of the `Sizedness` analysis for an individual item. -/// -/// This is a chain lattice of the form: -/// -/// ```ignore -/// NonZeroSized -/// | -/// DependsOnTypeParam -/// | -/// ZeroSized -/// ``` -/// -/// We initially assume that all types are `ZeroSized` and then update our -/// understanding as we learn more about each type. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord)] -pub enum SizednessResult { - /// Has some size that is known to be greater than zero. That doesn't mean - /// it has a static size, but it is not zero sized for sure. In other words, - /// it might contain an incomplete array or some other dynamically sized - /// type. - NonZeroSized, - - /// Whether this type is zero-sized or not depends on whether a type - /// parameter is zero-sized or not. - /// - /// For example, given these definitions: - /// - /// ```c++ - /// template - /// class Flongo : public T {}; - /// - /// class Empty {}; - /// - /// class NonEmpty { int x; }; - /// ``` - /// - /// Then `Flongo` is zero-sized, and needs an `_address` byte - /// inserted, while `Flongo` is *not* zero-sized, and should *not* - /// have an `_address` byte inserted. - /// - /// We don't properly handle this situation correctly right now: - /// https://github.com/rust-lang-nursery/rust-bindgen/issues/586 - DependsOnTypeParam, - - /// The type is zero-sized. - /// - /// This means that if it is a C++ type, and is not being used as a base - /// member, then we must add an `_address` byte to enforce the - /// unique-address-per-distinct-object-instance rule. - ZeroSized, -} - -impl Default for SizednessResult { - fn default() -> Self { - SizednessResult::ZeroSized - } -} - -impl cmp::PartialOrd for SizednessResult { - fn partial_cmp(&self, rhs: &Self) -> Option { - use self::SizednessResult::*; - - match (*self, *rhs) { - (x, y) if x == y => Some(cmp::Ordering::Equal), - (NonZeroSized, _) => Some(cmp::Ordering::Greater), - (_, NonZeroSized) => Some(cmp::Ordering::Less), - (DependsOnTypeParam, _) => Some(cmp::Ordering::Greater), - (_, DependsOnTypeParam) => Some(cmp::Ordering::Less), - _ => unreachable!(), - } - } -} - -impl SizednessResult { - /// Take the least upper bound of `self` and `rhs`. - pub fn join(self, rhs: Self) -> Self { - cmp::max(self, rhs) - } -} - -impl ops::BitOr for SizednessResult { - type Output = Self; - - fn bitor(self, rhs: SizednessResult) -> Self::Output { - self.join(rhs) - } -} - -impl ops::BitOrAssign for SizednessResult { - fn bitor_assign(&mut self, rhs: SizednessResult) { - *self = self.join(rhs) - } -} - -/// An analysis that computes the sizedness of all types. -/// -/// * For types with known sizes -- for example pointers, scalars, etc... -- -/// they are assigned `NonZeroSized`. -/// -/// * For compound structure types with one or more fields, they are assigned -/// `NonZeroSized`. -/// -/// * For compound structure types without any fields, the results of the bases -/// are `join`ed. -/// -/// * For type parameters, `DependsOnTypeParam` is assigned. -#[derive(Debug)] -pub struct SizednessAnalysis<'ctx> { - ctx: &'ctx BindgenContext, - dependencies: HashMap>, - // Incremental results of the analysis. Missing entries are implicitly - // considered `ZeroSized`. - sized: HashMap, -} - -impl<'ctx> SizednessAnalysis<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type is - // zero-sized or not. - EdgeKind::TemplateArgument | - EdgeKind::TemplateParameterDefinition | - EdgeKind::TemplateDeclaration | - EdgeKind::TypeReference | - EdgeKind::BaseMember | - EdgeKind::Field => true, - _ => false, - } - } - - /// Insert an incremental result, and return whether this updated our - /// knowledge of types and we should continue the analysis. - fn insert(&mut self, id: TypeId, result: SizednessResult) -> ConstrainResult { - trace!("inserting {:?} for {:?}", result, id); - - if let SizednessResult::ZeroSized = result { - return ConstrainResult::Same; - } - - match self.sized.entry(id) { - Entry::Occupied(mut entry) => { - if *entry.get() < result { - entry.insert(result); - ConstrainResult::Changed - } else { - ConstrainResult::Same - } - } - Entry::Vacant(entry) => { - entry.insert(result); - ConstrainResult::Changed - } - } - } - - fn forward(&mut self, from: TypeId, to: TypeId) -> ConstrainResult { - match self.sized.get(&from).cloned() { - None => ConstrainResult::Same, - Some(r) => self.insert(to, r), - } - } -} - -impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> { - type Node = TypeId; - type Extra = &'ctx BindgenContext; - type Output = HashMap; - - fn new(ctx: &'ctx BindgenContext) -> SizednessAnalysis<'ctx> { - let dependencies = generate_dependencies(ctx, Self::consider_edge) - .into_iter() - .filter_map(|(id, sub_ids)| { - id.as_type_id(ctx) - .map(|id| { - ( - id, - sub_ids.into_iter() - .filter_map(|s| s.as_type_id(ctx)) - .collect::>() - ) - }) - }) - .collect(); - - let sized = HashMap::new(); - - SizednessAnalysis { - ctx, - dependencies, - sized, - } - } - - fn initial_worklist(&self) -> Vec { - self.ctx - .whitelisted_items() - .iter() - .cloned() - .filter_map(|id| id.as_type_id(self.ctx)) - .collect() - } - - fn constrain(&mut self, id: TypeId) -> ConstrainResult { - trace!("constrain {:?}", id); - - if let Some(SizednessResult::NonZeroSized) = self.sized.get(&id).cloned() { - trace!(" already know it is not zero-sized"); - return ConstrainResult::Same; - } - - if id.has_vtable_ptr(self.ctx) { - trace!(" has an explicit vtable pointer, therefore is not zero-sized"); - return self.insert(id, SizednessResult::NonZeroSized); - } - - let ty = self.ctx.resolve_type(id); - - if id.is_opaque(self.ctx, &()) { - trace!(" type is opaque; checking layout..."); - let result = ty.layout(self.ctx) - .map_or(SizednessResult::ZeroSized, |l| { - if l.size == 0 { - trace!(" ...layout has size == 0"); - SizednessResult::ZeroSized - } else { - trace!(" ...layout has size > 0"); - SizednessResult::NonZeroSized - } - }); - return self.insert(id, result); - } - - match *ty.kind() { - TypeKind::Void => { - trace!(" void is zero-sized"); - self.insert(id, SizednessResult::ZeroSized) - } - - TypeKind::TypeParam => { - trace!(" type params sizedness depends on what they're \ - instantiated as"); - self.insert(id, SizednessResult::DependsOnTypeParam) - } - - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::NullPtr | - TypeKind::BlockPointer | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::Pointer(..) => { - trace!(" {:?} is known not to be zero-sized", ty.kind()); - self.insert(id, SizednessResult::NonZeroSized) - } - - TypeKind::ObjCInterface(..) => { - trace!(" obj-c interfaces always have at least the `isa` pointer"); - self.insert(id, SizednessResult::NonZeroSized) - } - - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) | - TypeKind::ResolvedTypeRef(t) => { - trace!(" aliases and type refs forward to their inner type"); - self.forward(t, id) - } - - TypeKind::TemplateInstantiation(ref inst) => { - trace!(" template instantiations are zero-sized if their \ - definition is zero-sized"); - self.forward(inst.template_definition(), id) - } - - TypeKind::Array(_, 0) => { - trace!(" arrays of zero elements are zero-sized"); - self.insert(id, SizednessResult::ZeroSized) - } - TypeKind::Array(..) => { - trace!(" arrays of > 0 elements are not zero-sized"); - self.insert(id, SizednessResult::NonZeroSized) - } - - TypeKind::Comp(ref info) => { - trace!(" comp considers its own fields and bases"); - - if !info.fields().is_empty() { - return self.insert(id, SizednessResult::NonZeroSized); - } - - let result = info.base_members() - .iter() - .filter_map(|base| self.sized.get(&base.ty)) - .fold(SizednessResult::ZeroSized, |a, b| a.join(*b)); - - self.insert(id, result) - } - - TypeKind::Opaque => { - unreachable!("covered by the .is_opaque() check above") - } - - TypeKind::UnresolvedTypeRef(..) => { - unreachable!("Should have been resolved after parsing!"); - } - } - } - - fn each_depending_on(&self, id: TypeId, mut f: F) - where - F: FnMut(TypeId), - { - if let Some(edges) = self.dependencies.get(&id) { - for ty in edges { - trace!("enqueue {:?} into worklist", ty); - f(*ty); - } - } - } -} - -impl<'ctx> From> for HashMap { - fn from(analysis: SizednessAnalysis<'ctx>) -> Self { - // We let the lack of an entry mean "ZeroSized" to save space. - extra_assert!(analysis.sized.values().all(|v| { - *v != SizednessResult::ZeroSized - })); - - analysis.sized - } -} - -/// A convenience trait for querying whether some type or id is sized. -/// -/// This is not for _computing_ whether the thing is sized, it is for looking up -/// the results of the `Sizedness` analysis's computations for a specific thing. -pub trait Sizedness { - /// Get the sizedness of this type. - fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult; - - /// Is the sizedness for this type `SizednessResult::ZeroSized`? - fn is_zero_sized(&self, ctx: &BindgenContext) -> bool { - self.sizedness(ctx) == SizednessResult::ZeroSized - } -} diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs deleted file mode 100644 index 00504aa40e..0000000000 --- a/src/ir/analysis/template_params.rs +++ /dev/null @@ -1,588 +0,0 @@ -//! Discover which template type parameters are actually used. -//! -//! ### Why do we care? -//! -//! C++ allows ignoring template parameters, while Rust does not. Usually we can -//! blindly stick a `PhantomData` inside a generic Rust struct to make up for -//! this. That doesn't work for templated type aliases, however: -//! -//! ```C++ -//! template -//! using Fml = int; -//! ``` -//! -//! If we generate the naive Rust code for this alias, we get: -//! -//! ```ignore -//! pub type Fml = ::std::os::raw::int; -//! ``` -//! -//! And this is rejected by `rustc` due to the unused type parameter. -//! -//! (Aside: in these simple cases, `libclang` will often just give us the -//! aliased type directly, and we will never even know we were dealing with -//! aliases, let alone templated aliases. It's the more convoluted scenarios -//! where we get to have some fun...) -//! -//! For such problematic template aliases, we could generate a tuple whose -//! second member is a `PhantomData`. Or, if we wanted to go the extra mile, -//! we could even generate some smarter wrapper that implements `Deref`, -//! `DerefMut`, `From`, `Into`, `AsRef`, and `AsMut` to the actually aliased -//! type. However, this is still lackluster: -//! -//! 1. Even with a billion conversion-trait implementations, using the generated -//! bindings is rather un-ergonomic. -//! 2. With either of these solutions, we need to keep track of which aliases -//! we've transformed like this in order to generate correct uses of the -//! wrapped type. -//! -//! Given that we have to properly track which template parameters ended up used -//! for (2), we might as well leverage that information to make ergonomic -//! bindings that don't contain any unused type parameters at all, and -//! completely avoid the pain of (1). -//! -//! ### How do we determine which template parameters are used? -//! -//! Determining which template parameters are actually used is a trickier -//! problem than it might seem at a glance. On the one hand, trivial uses are -//! easy to detect: -//! -//! ```C++ -//! template -//! class Foo { -//! T trivial_use_of_t; -//! }; -//! ``` -//! -//! It gets harder when determining if one template parameter is used depends on -//! determining if another template parameter is used. In this example, whether -//! `U` is used depends on whether `T` is used. -//! -//! ```C++ -//! template -//! class DoesntUseT { -//! int x; -//! }; -//! -//! template -//! class Fml { -//! DoesntUseT lololol; -//! }; -//! ``` -//! -//! We can express the set of used template parameters as a constraint solving -//! problem (where the set of template parameters used by a given IR item is the -//! union of its sub-item's used template parameters) and iterate to a -//! fixed-point. -//! -//! We use the `ir::analysis::MonotoneFramework` infrastructure for this -//! fix-point analysis, where our lattice is the mapping from each IR item to -//! the powerset of the template parameters that appear in the input C++ header, -//! our join function is set union. The set of template parameters appearing in -//! the program is finite, as is the number of IR items. We start at our -//! lattice's bottom element: every item mapping to an empty set of template -//! parameters. Our analysis only adds members to each item's set of used -//! template parameters, never removes them, so it is monotone. Because our -//! lattice is finite and our constraint function is monotone, iteration to a -//! fix-point will terminate. -//! -//! See `src/ir/analysis.rs` for more. - -use super::{ConstrainResult, MonotoneFramework}; -use ir::context::{BindgenContext, ItemId}; -use ir::item::{Item, ItemSet}; -use ir::template::{TemplateInstantiation, TemplateParameters}; -use ir::traversal::{EdgeKind, Trace}; -use ir::ty::TypeKind; -use std::collections::{HashMap, HashSet}; - -/// An analysis that finds for each IR item its set of template parameters that -/// it uses. -/// -/// We use the monotone constraint function `template_param_usage`, defined as -/// follows: -/// -/// * If `T` is a named template type parameter, it trivially uses itself: -/// -/// ```ignore -/// template_param_usage(T) = { T } -/// ``` -/// -/// * If `inst` is a template instantiation, `inst.args` are the template -/// instantiation's template arguments, `inst.def` is the template definition -/// being instantiated, and `inst.def.params` is the template definition's -/// template parameters, then the instantiation's usage is the union of each -/// of its arguments' usages *if* the corresponding template parameter is in -/// turn used by the template definition: -/// -/// ```ignore -/// template_param_usage(inst) = union( -/// template_param_usage(inst.args[i]) -/// for i in 0..length(inst.args.length) -/// if inst.def.params[i] in template_param_usage(inst.def) -/// ) -/// ``` -/// -/// * Finally, for all other IR item kinds, we use our lattice's `join` -/// operation: set union with each successor of the given item's template -/// parameter usage: -/// -/// ```ignore -/// template_param_usage(v) = -/// union(template_param_usage(w) for w in successors(v)) -/// ``` -/// -/// Note that we ignore certain edges in the graph, such as edges from a -/// template declaration to its template parameters' definitions for this -/// analysis. If we didn't, then we would mistakenly determine that ever -/// template parameter is always used. -/// -/// The final wrinkle is handling of blacklisted types. Normally, we say that -/// the set of whitelisted items is the transitive closure of items explicitly -/// called out for whitelisting, *without* any items explicitly called out as -/// blacklisted. However, for the purposes of this analysis's correctness, we -/// simplify and consider run the analysis on the full transitive closure of -/// whitelisted items. We do, however, treat instantiations of blacklisted items -/// specially; see `constrain_instantiation_of_blacklisted_template` and its -/// documentation for details. -#[derive(Debug, Clone)] -pub struct UsedTemplateParameters<'ctx> { - ctx: &'ctx BindgenContext, - - // The Option is only there for temporary moves out of the hash map. See the - // comments in `UsedTemplateParameters::constrain` below. - used: HashMap>, - - dependencies: HashMap>, - - // The set of whitelisted items, without any blacklisted items reachable - // from the whitelisted items which would otherwise be considered - // whitelisted as well. - whitelisted_items: HashSet, -} - -impl<'ctx> UsedTemplateParameters<'ctx> { - fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // For each of these kinds of edges, if the referent uses a template - // parameter, then it should be considered that the origin of the - // edge also uses the template parameter. - EdgeKind::TemplateArgument | - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::Constructor | - EdgeKind::Destructor | - EdgeKind::VarType | - EdgeKind::FunctionReturn | - EdgeKind::FunctionParameter | - EdgeKind::TypeReference => true, - - // An inner var or type using a template parameter is orthogonal - // from whether we use it. See template-param-usage-{6,11}.hpp. - EdgeKind::InnerVar | EdgeKind::InnerType => false, - - // We can't emit machine code for new monomorphizations of class - // templates' methods (and don't detect explicit instantiations) so - // we must ignore template parameters that are only used by - // methods. This doesn't apply to a function type's return or - // parameter types, however, because of type aliases of function - // pointers that use template parameters, eg - // tests/headers/struct_with_typedef_template_arg.hpp - EdgeKind::Method => false, - - // If we considered these edges, we would end up mistakenly claiming - // that every template parameter always used. - EdgeKind::TemplateDeclaration | - EdgeKind::TemplateParameterDefinition => false, - - // Since we have to be careful about which edges we consider for - // this analysis to be correct, we ignore generic edges. We also - // avoid a `_` wild card to force authors of new edge kinds to - // determine whether they need to be considered by this analysis. - EdgeKind::Generic => false, - } - } - - fn take_this_id_usage_set>(&mut self, this_id: Id) -> ItemSet { - let this_id = this_id.into(); - self.used - .get_mut(&this_id) - .expect( - "Should have a set of used template params for every item \ - id", - ) - .take() - .expect( - "Should maintain the invariant that all used template param \ - sets are `Some` upon entry of `constrain`", - ) - } - - /// We say that blacklisted items use all of their template parameters. The - /// blacklisted type is most likely implemented explicitly by the user, - /// since it won't be in the generated bindings, and we don't know exactly - /// what they'll to with template parameters, but we can push the issue down - /// the line to them. - fn constrain_instantiation_of_blacklisted_template( - &self, - this_id: ItemId, - used_by_this_id: &mut ItemSet, - instantiation: &TemplateInstantiation, - ) { - trace!( - " instantiation of blacklisted template, uses all template \ - arguments" - ); - - let args = instantiation - .template_arguments() - .into_iter() - .map(|a| { - a.into_resolver() - .through_type_refs() - .through_type_aliases() - .resolve(self.ctx) - .id() - }) - .filter(|a| *a != this_id) - .flat_map(|a| { - self.used - .get(&a) - .expect("Should have a used entry for the template arg") - .as_ref() - .expect( - "Because a != this_id, and all used template \ - param sets other than this_id's are `Some`, \ - a's used template param set should be `Some`", - ) - .iter() - .cloned() - }); - - used_by_this_id.extend(args); - } - - /// A template instantiation's concrete template argument is only used if - /// the template definition uses the corresponding template parameter. - fn constrain_instantiation( - &self, - this_id: ItemId, - used_by_this_id: &mut ItemSet, - instantiation: &TemplateInstantiation, - ) { - trace!(" template instantiation"); - - let decl = self.ctx.resolve_type(instantiation.template_definition()); - let args = instantiation.template_arguments(); - - let params = decl.self_template_params(self.ctx).unwrap_or(vec![]); - - debug_assert!(this_id != instantiation.template_definition()); - let used_by_def = self.used - .get(&instantiation.template_definition().into()) - .expect("Should have a used entry for instantiation's template definition") - .as_ref() - .expect("And it should be Some because only this_id's set is None, and an \ - instantiation's template definition should never be the \ - instantiation itself"); - - for (arg, param) in args.iter().zip(params.iter()) { - trace!( - " instantiation's argument {:?} is used if definition's \ - parameter {:?} is used", - arg, - param - ); - - if used_by_def.contains(¶m.into()) { - trace!(" param is used by template definition"); - - let arg = arg.into_resolver() - .through_type_refs() - .through_type_aliases() - .resolve(self.ctx) - .id(); - - if arg == this_id { - continue; - } - - let used_by_arg = self.used - .get(&arg) - .expect("Should have a used entry for the template arg") - .as_ref() - .expect( - "Because arg != this_id, and all used template \ - param sets other than this_id's are `Some`, \ - arg's used template param set should be \ - `Some`", - ) - .iter() - .cloned(); - used_by_this_id.extend(used_by_arg); - } - } - } - - /// The join operation on our lattice: the set union of all of this id's - /// successors. - fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) { - trace!(" other item: join with successors' usage"); - - item.trace( - self.ctx, - &mut |sub_id, edge_kind| { - // Ignore ourselves, since union with ourself is a - // no-op. Ignore edges that aren't relevant to the - // analysis. - if sub_id == item.id() || !Self::consider_edge(edge_kind) { - return; - } - - let used_by_sub_id = self.used - .get(&sub_id) - .expect("Should have a used set for the sub_id successor") - .as_ref() - .expect( - "Because sub_id != id, and all used template \ - param sets other than id's are `Some`, \ - sub_id's used template param set should be \ - `Some`", - ) - .iter() - .cloned(); - - trace!( - " union with {:?}'s usage: {:?}", - sub_id, - used_by_sub_id.clone().collect::>() - ); - - used_by_this_id.extend(used_by_sub_id); - }, - &(), - ); - } -} - -impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashMap; - - fn new( - ctx: &'ctx BindgenContext, - ) -> UsedTemplateParameters<'ctx> { - let mut used = HashMap::new(); - let mut dependencies = HashMap::new(); - let whitelisted_items: HashSet<_> = - ctx.whitelisted_items().iter().cloned().collect(); - - let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items - .iter() - .cloned() - .flat_map(|i| { - let mut reachable = vec![i]; - i.trace(ctx, &mut |s, _| { reachable.push(s); }, &()); - reachable - }) - .collect(); - - for item in whitelisted_and_blacklisted_items { - dependencies.entry(item).or_insert(vec![]); - used.entry(item).or_insert(Some(ItemSet::new())); - - { - // We reverse our natural IR graph edges to find dependencies - // between nodes. - item.trace( - ctx, - &mut |sub_item: ItemId, _| { - used.entry(sub_item).or_insert(Some(ItemSet::new())); - dependencies.entry(sub_item).or_insert(vec![]).push( - item, - ); - }, - &(), - ); - } - - // Additionally, whether a template instantiation's template - // arguments are used depends on whether the template declaration's - // generic template parameters are used. - ctx.resolve_item(item).as_type().map(|ty| match ty.kind() { - &TypeKind::TemplateInstantiation(ref inst) => { - let decl = ctx.resolve_type(inst.template_definition()); - let args = inst.template_arguments(); - - // Although template definitions should always have - // template parameters, there is a single exception: - // opaque templates. Hence the unwrap_or. - let params = - decl.self_template_params(ctx).unwrap_or(vec![]); - - for (arg, param) in args.iter().zip(params.iter()) { - let arg = arg.into_resolver() - .through_type_aliases() - .through_type_refs() - .resolve(ctx) - .id(); - - let param = param - .into_resolver() - .through_type_aliases() - .through_type_refs() - .resolve(ctx) - .id(); - - used.entry(arg).or_insert(Some(ItemSet::new())); - used.entry(param).or_insert(Some(ItemSet::new())); - - dependencies.entry(arg).or_insert(vec![]).push(param); - } - } - _ => {} - }); - } - - if cfg!(feature = "testing_only_extra_assertions") { - // Invariant: The `used` map has an entry for every whitelisted - // item, as well as all explicitly blacklisted items that are - // reachable from whitelisted items. - // - // Invariant: the `dependencies` map has an entry for every - // whitelisted item. - // - // (This is so that every item we call `constrain` on is guaranteed - // to have a set of template parameters, and we can allow - // blacklisted templates to use all of their parameters). - for item in whitelisted_items.iter() { - extra_assert!(used.contains_key(item)); - extra_assert!(dependencies.contains_key(item)); - item.trace( - ctx, - &mut |sub_item, _| { - extra_assert!(used.contains_key(&sub_item)); - extra_assert!(dependencies.contains_key(&sub_item)); - }, - &(), - ) - } - } - - UsedTemplateParameters { - ctx: ctx, - used: used, - dependencies: dependencies, - whitelisted_items: whitelisted_items, - } - } - - fn initial_worklist(&self) -> Vec { - // The transitive closure of all whitelisted items, including explicitly - // blacklisted items. - self.ctx - .whitelisted_items() - .iter() - .cloned() - .flat_map(|i| { - let mut reachable = vec![i]; - i.trace(self.ctx, &mut |s, _| { reachable.push(s); }, &()); - reachable - }) - .collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - // Invariant: all hash map entries' values are `Some` upon entering and - // exiting this method. - extra_assert!(self.used.values().all(|v| v.is_some())); - - // Take the set for this id out of the hash map while we mutate it based - // on other hash map entries. We *must* put it back into the hash map at - // the end of this method. This allows us to side-step HashMap's lack of - // an analog to slice::split_at_mut. - let mut used_by_this_id = self.take_this_id_usage_set(id); - - trace!("constrain {:?}", id); - trace!(" initially, used set is {:?}", used_by_this_id); - - let original_len = used_by_this_id.len(); - - let item = self.ctx.resolve_item(id); - let ty_kind = item.as_type().map(|ty| ty.kind()); - match ty_kind { - // Named template type parameters trivially use themselves. - Some(&TypeKind::TypeParam) => { - trace!(" named type, trivially uses itself"); - used_by_this_id.insert(id); - } - // Template instantiations only use their template arguments if the - // template definition uses the corresponding template parameter. - Some(&TypeKind::TemplateInstantiation(ref inst)) => { - if self.whitelisted_items.contains( - &inst.template_definition().into(), - ) - { - self.constrain_instantiation( - id, - &mut used_by_this_id, - inst, - ); - } else { - self.constrain_instantiation_of_blacklisted_template( - id, - &mut used_by_this_id, - inst, - ); - } - } - // Otherwise, add the union of each of its referent item's template - // parameter usage. - _ => self.constrain_join(&mut used_by_this_id, item), - } - - trace!(" finally, used set is {:?}", used_by_this_id); - - let new_len = used_by_this_id.len(); - assert!( - new_len >= original_len, - "This is the property that ensures this function is monotone -- \ - if it doesn't hold, the analysis might never terminate!" - ); - - // Put the set back in the hash map and restore our invariant. - debug_assert!(self.used[&id].is_none()); - self.used.insert(id, Some(used_by_this_id)); - extra_assert!(self.used.values().all(|v| v.is_some())); - - if new_len != original_len { - ConstrainResult::Changed - } else { - ConstrainResult::Same - } - } - - fn each_depending_on(&self, item: ItemId, mut f: F) - where - F: FnMut(ItemId), - { - if let Some(edges) = self.dependencies.get(&item) { - for item in edges { - trace!("enqueue {:?} into worklist", item); - f(*item); - } - } - } -} - -impl<'ctx> From> - for HashMap { - fn from(used_templ_params: UsedTemplateParameters<'ctx>) -> Self { - used_templ_params - .used - .into_iter() - .map(|(k, v)| (k, v.unwrap())) - .collect() - } -} diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs deleted file mode 100644 index bc57b555ac..0000000000 --- a/src/ir/annotations.rs +++ /dev/null @@ -1,189 +0,0 @@ -//! Types and functions related to bindgen annotation comments. -//! -//! Users can add annotations in doc comments to types that they would like to -//! replace other types with, mark as opaque, etc. This module deals with all of -//! that stuff. - -use clang; - -/// What kind of accessor should we provide for a field? -#[derive(Copy, PartialEq, Clone, Debug)] -pub enum FieldAccessorKind { - /// No accessor. - None, - /// Plain accessor. - Regular, - /// Unsafe accessor. - Unsafe, - /// Immutable accessor. - Immutable, -} - -/// Annotations for a given item, or a field. -/// -/// You can see the kind of comments that are accepted in the Doxygen -/// documentation: -/// -/// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html -#[derive(Clone, PartialEq, Debug)] -pub struct Annotations { - /// Whether this item is marked as opaque. Only applies to types. - opaque: bool, - /// Whether this item should be hidden from the output. Only applies to - /// types, or enum variants. - hide: bool, - /// Whether this type should be replaced by another. The name is a - /// namespace-aware path. - use_instead_of: Option>, - /// Manually disable deriving copy/clone on this type. Only applies to - /// struct or union types. - disallow_copy: bool, - /// Whether fields should be marked as private or not. You can set this on - /// structs (it will apply to all the fields), or individual fields. - private_fields: Option, - /// The kind of accessor this field will have. Also can be applied to - /// structs so all the fields inside share it by default. - accessor_kind: Option, - /// Whether this enum variant should be constified. - /// - /// This is controlled by the `constant` attribute, this way: - /// - /// ```cpp - /// enum Foo { - /// Bar = 0, /**<
*/ - /// Baz = 0, - /// }; - /// ``` - /// - /// In that case, bindgen will generate a constant for `Bar` instead of - /// `Baz`. - constify_enum_variant: bool, -} - -fn parse_accessor(s: &str) -> FieldAccessorKind { - match s { - "false" => FieldAccessorKind::None, - "unsafe" => FieldAccessorKind::Unsafe, - "immutable" => FieldAccessorKind::Immutable, - _ => FieldAccessorKind::Regular, - } -} - -impl Default for Annotations { - fn default() -> Self { - Annotations { - opaque: false, - hide: false, - use_instead_of: None, - disallow_copy: false, - private_fields: None, - accessor_kind: None, - constify_enum_variant: false, - } - } -} - -impl Annotations { - /// Construct new annotations for the given cursor and its bindgen comments - /// (if any). - pub fn new(cursor: &clang::Cursor) -> Option { - let mut anno = Annotations::default(); - let mut matched_one = false; - anno.parse(&cursor.comment(), &mut matched_one); - - if matched_one { Some(anno) } else { None } - } - - /// Should this type be hidden? - pub fn hide(&self) -> bool { - self.hide - } - - /// Should this type be opaque? - pub fn opaque(&self) -> bool { - self.opaque - } - - /// For a given type, indicates the type it should replace. - /// - /// For example, in the following code: - /// - /// ```cpp - /// - /// /**
*/ - /// struct Foo { int x; }; - /// - /// struct Bar { char foo; }; - /// ``` - /// - /// the generated code would look something like: - /// - /// ``` - /// /**
*/ - /// struct Bar { - /// x: ::std::os::raw::c_int, - /// }; - /// ``` - /// - /// That is, code for `Foo` is used to generate `Bar`. - pub fn use_instead_of(&self) -> Option<&[String]> { - self.use_instead_of.as_ref().map(|s| &**s) - } - - /// Should we avoid implementing the `Copy` trait? - pub fn disallow_copy(&self) -> bool { - self.disallow_copy - } - - /// Should the fields be private? - pub fn private_fields(&self) -> Option { - self.private_fields - } - - /// What kind of accessors should we provide for this type's fields? - pub fn accessor_kind(&self) -> Option { - self.accessor_kind - } - - fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) { - use clang_sys::CXComment_HTMLStartTag; - if comment.kind() == CXComment_HTMLStartTag && - comment.get_tag_name() == "div" && - comment.get_tag_attrs().next().map_or(false, |attr| { - attr.name == "rustbindgen" - }) - { - *matched = true; - for attr in comment.get_tag_attrs() { - match attr.name.as_str() { - "opaque" => self.opaque = true, - "hide" => self.hide = true, - "nocopy" => self.disallow_copy = true, - "replaces" => { - self.use_instead_of = - Some( - attr.value.split("::").map(Into::into).collect(), - ) - } - "private" => { - self.private_fields = Some(attr.value != "false") - } - "accessor" => { - self.accessor_kind = Some(parse_accessor(&attr.value)) - } - "constant" => self.constify_enum_variant = true, - _ => {} - } - } - } - - for child in comment.get_children() { - self.parse(&child, matched); - } - } - - /// Returns whether we've parsed a "constant" attribute. - pub fn constify_enum_variant(&self) -> bool { - self.constify_enum_variant - } -} diff --git a/src/ir/comment.rs b/src/ir/comment.rs deleted file mode 100644 index afa2a38589..0000000000 --- a/src/ir/comment.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! Utilities for manipulating C/C++ comments. - -use std::iter; - -/// The type of a comment. -#[derive(Debug, PartialEq, Eq)] -enum Kind { - /// A `///` comment, or something of the like. - /// All lines in a comment should start with the same symbol. - SingleLines, - /// A `/**` comment, where each other line can start with `*` and the - /// entire block ends with `*/`. - MultiLine, -} - -/// Preprocesses a C/C++ comment so that it is a valid Rust comment. -pub fn preprocess(comment: &str, indent: usize) -> String { - match self::kind(&comment) { - Some(Kind::SingleLines) => preprocess_single_lines(comment, indent), - Some(Kind::MultiLine) => preprocess_multi_line(comment, indent), - None => comment.to_owned(), - } -} - -/// Gets the kind of the doc comment, if it is one. -fn kind(comment: &str) -> Option { - if comment.starts_with("/*") { - Some(Kind::MultiLine) - } else if comment.starts_with("//") { - Some(Kind::SingleLines) - } else { - None - } -} - -fn make_indent(indent: usize) -> String { - const RUST_INDENTATION: usize = 4; - - iter::repeat(' ').take(indent * RUST_INDENTATION).collect() -} - -/// Preprocesses mulitple single line comments. -/// -/// Handles lines starting with both `//` and `///`. -fn preprocess_single_lines(comment: &str, indent: usize) -> String { - debug_assert!(comment.starts_with("//"), "comment is not single line"); - - let indent = make_indent(indent); - let mut is_first = true; - let lines: Vec<_> = comment - .lines() - .map(|l| l.trim_left_matches('/').trim()) - .map(|l| { - let indent = if is_first { "" } else { &*indent }; - is_first = false; - let maybe_space = if l.is_empty() { "" } else { " " }; - format!("{}///{}{}", indent, maybe_space, l) - }) - .collect(); - lines.join("\n") -} - -fn preprocess_multi_line(comment: &str, indent: usize) -> String { - let comment = comment - .trim_left_matches('/') - .trim_left_matches('*') - .trim_left_matches('!') - .trim_right_matches('/') - .trim_right_matches('*') - .trim(); - - let indent = make_indent(indent); - // Strip any potential `*` characters preceding each line. - let mut is_first = true; - let mut lines: Vec<_> = comment.lines() - .map(|line| line.trim().trim_left_matches('*').trim()) - .skip_while(|line| line.is_empty()) // Skip the first empty lines. - .map(|line| { - let indent = if is_first { "" } else { &*indent }; - is_first = false; - let maybe_space = if line.is_empty() { "" } else { " " }; - format!("{}///{}{}", indent, maybe_space, line) - }) - .collect(); - - // Remove the trailing line corresponding to the `*/`. - let last_line_is_empty = lines.last().map_or(false, |l| l.is_empty()); - - if last_line_is_empty { - lines.pop(); - } - - lines.join("\n") -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn picks_up_single_and_multi_line_doc_comments() { - assert_eq!(kind("/// hello"), Some(Kind::SingleLines)); - assert_eq!(kind("/** world */"), Some(Kind::MultiLine)); - } - - #[test] - fn processes_single_lines_correctly() { - assert_eq!(preprocess("/// hello", 0), "/// hello"); - assert_eq!(preprocess("// hello", 0), "/// hello"); - } - - #[test] - fn processes_multi_lines_correctly() { - assert_eq!( - preprocess("/** hello \n * world \n * foo \n */", 0), - "/// hello\n/// world\n/// foo" - ); - - assert_eq!( - preprocess("/**\nhello\n*world\n*foo\n*/", 0), - "/// hello\n/// world\n/// foo" - ); - } -} diff --git a/src/ir/comp.rs b/src/ir/comp.rs deleted file mode 100644 index 8c2be498e9..0000000000 --- a/src/ir/comp.rs +++ /dev/null @@ -1,1725 +0,0 @@ -//! Compound types (unions and structs) in our intermediate representation. - -use super::analysis::Sizedness; -use super::annotations::Annotations; -use super::context::{BindgenContext, FunctionId, ItemId, TypeId, VarId}; -use super::dot::DotAttributes; -use super::item::{IsOpaque, Item}; -use super::layout::Layout; -// use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use super::template::TemplateParameters; -use super::traversal::{EdgeKind, Trace, Tracer}; -use clang; -use codegen::struct_layout::{align_to, bytes_from_bits_pow2}; -use ir::derive::CanDeriveCopy; -use parse::{ClangItemParser, ParseError}; -use peeking_take_while::PeekableExt; -use std::cmp; -use std::io; -use std::mem; -use std::collections::HashMap; - -/// The kind of compound type. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum CompKind { - /// A struct. - Struct, - /// A union. - Union, -} - -/// The kind of C++ method. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum MethodKind { - /// A constructor. We represent it as method for convenience, to avoid code - /// duplication. - Constructor, - /// A destructor. - Destructor, - /// A virtual destructor. - VirtualDestructor { - /// Whether it's pure virtual. - pure_virtual: bool, - }, - /// A static method. - Static, - /// A normal method. - Normal, - /// A virtual method. - Virtual { - /// Whether it's pure virtual. - pure_virtual: bool, - }, -} - - -impl MethodKind { - /// Is this a destructor method? - pub fn is_destructor(&self) -> bool { - match *self { - MethodKind::Destructor | - MethodKind::VirtualDestructor { .. } => true, - _ => false, - } - } - - /// Is this a pure virtual method? - pub fn is_pure_virtual(&self) -> bool { - match *self { - MethodKind::Virtual { pure_virtual } | - MethodKind::VirtualDestructor { pure_virtual } => pure_virtual, - _ => false, - } - } -} - -/// A struct representing a C++ method, either static, normal, or virtual. -#[derive(Debug)] -pub struct Method { - kind: MethodKind, - /// The signature of the method. Take into account this is not a `Type` - /// item, but a `Function` one. - /// - /// This is tricky and probably this field should be renamed. - signature: FunctionId, - is_const: bool, -} - -impl Method { - /// Construct a new `Method`. - pub fn new(kind: MethodKind, signature: FunctionId, is_const: bool) -> Self { - Method { - kind, - signature, - is_const, - } - } - - /// What kind of method is this? - pub fn kind(&self) -> MethodKind { - self.kind - } - - /// Is this a constructor? - pub fn is_constructor(&self) -> bool { - self.kind == MethodKind::Constructor - } - - /// Is this a virtual method? - pub fn is_virtual(&self) -> bool { - match self.kind { - MethodKind::Virtual { .. } | - MethodKind::VirtualDestructor { .. } => true, - _ => false, - } - } - - /// Is this a static method? - pub fn is_static(&self) -> bool { - self.kind == MethodKind::Static - } - - /// Get the id for the `Function` signature for this method. - pub fn signature(&self) -> FunctionId { - self.signature - } - - /// Is this a const qualified method? - pub fn is_const(&self) -> bool { - self.is_const - } -} - -/// Methods common to the various field types. -pub trait FieldMethods { - /// Get the name of this field. - fn name(&self) -> Option<&str>; - - /// Get the type of this field. - fn ty(&self) -> TypeId; - - /// Get the comment for this field. - fn comment(&self) -> Option<&str>; - - /// If this is a bitfield, how many bits does it need? - fn bitfield_width(&self) -> Option; - - /// Is this field marked as `mutable`? - fn is_mutable(&self) -> bool; - - /// Get the annotations for this field. - fn annotations(&self) -> &Annotations; - - /// The offset of the field (in bits) - fn offset(&self) -> Option; -} - -/// A contiguous set of logical bitfields that live within the same physical -/// allocation unit. See 9.2.4 [class.bit] in the C++ standard and [section -/// 2.4.II.1 in the Itanium C++ -/// ABI](http://itanium-cxx-abi.github.io/cxx-abi/abi.html#class-types). -#[derive(Debug)] -pub struct BitfieldUnit { - nth: usize, - layout: Layout, - bitfields: Vec, -} - -impl BitfieldUnit { - /// Get the 1-based index of this bitfield unit within its containing - /// struct. Useful for generating a Rust struct's field name for this unit - /// of bitfields. - pub fn nth(&self) -> usize { - self.nth - } - - /// Get the layout within which these bitfields reside. - pub fn layout(&self) -> Layout { - self.layout - } - - /// Get the bitfields within this unit. - pub fn bitfields(&self) -> &[Bitfield] { - &self.bitfields - } -} - -/// A struct representing a C++ field. -#[derive(Debug)] -pub enum Field { - /// A normal data member. - DataMember(FieldData), - - /// A physical allocation unit containing many logical bitfields. - Bitfields(BitfieldUnit), -} - -impl Field { - /// Get this field's layout. - pub fn layout(&self, ctx: &BindgenContext) -> Option { - match *self { - Field::Bitfields(BitfieldUnit { - layout, .. - }) => Some(layout), - Field::DataMember(ref data) => { - ctx.resolve_type(data.ty).layout(ctx) - } - } - } -} - -impl Trace for Field { - type Extra = (); - - fn trace(&self, _: &BindgenContext, tracer: &mut T, _: &()) - where - T: Tracer, - { - match *self { - Field::DataMember(ref data) => { - tracer.visit_kind(data.ty.into(), EdgeKind::Field); - } - Field::Bitfields(BitfieldUnit { - ref bitfields, .. - }) => { - for bf in bitfields { - tracer.visit_kind(bf.ty().into(), EdgeKind::Field); - } - } - } - } -} - -impl DotAttributes for Field { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - match *self { - Field::DataMember(ref data) => data.dot_attributes(ctx, out), - Field::Bitfields(BitfieldUnit { - layout, - ref bitfields, - .. - }) => { - writeln!( - out, - r#" - bitfield unit - - - - - - - - - "#, - layout.size, - layout.align - )?; - for bf in bitfields { - bf.dot_attributes(ctx, out)?; - } - writeln!(out, "
unit.size{}
unit.align{}
") - } - } - } -} - -impl DotAttributes for FieldData { - fn dot_attributes( - &self, - _ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!( - out, - "{}{:?}", - self.name().unwrap_or("(anonymous)"), - self.ty() - ) - } -} - -impl DotAttributes for Bitfield { - fn dot_attributes( - &self, - _ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!( - out, - "{} : {}{:?}", - self.name().unwrap_or("(anonymous)"), - self.width(), - self.ty() - ) - } -} - -/// A logical bitfield within some physical bitfield allocation unit. -#[derive(Debug)] -pub struct Bitfield { - /// Index of the bit within this bitfield's allocation unit where this - /// bitfield's bits begin. - offset_into_unit: usize, - - /// The field data for this bitfield. - data: FieldData, - - /// Name of the generated Rust getter for this bitfield. - /// - /// Should be assigned before codegen. - getter_name: Option, - - /// Name of the generated Rust setter for this bitfield. - /// - /// Should be assigned before codegen. - setter_name: Option, -} - -impl Bitfield { - /// Construct a new bitfield. - fn new(offset_into_unit: usize, raw: RawField) -> Bitfield { - assert!(raw.bitfield_width().is_some()); - - Bitfield { - offset_into_unit, - data: raw.0, - getter_name: None, - setter_name: None, - } - } - - /// Get the index of the bit within this bitfield's allocation unit where - /// this bitfield begins. - pub fn offset_into_unit(&self) -> usize { - self.offset_into_unit - } - - /// Get the mask value that when &'ed with this bitfield's allocation unit - /// produces this bitfield's value. - pub fn mask(&self) -> u64 { - use std::mem; - use std::u64; - - let unoffseted_mask = - if self.width() as u64 == mem::size_of::() as u64 * 8 { - u64::MAX - } else { - ((1u64 << self.width()) - 1u64) - }; - - unoffseted_mask << self.offset_into_unit() - } - - /// Get the bit width of this bitfield. - pub fn width(&self) -> u32 { - self.data.bitfield_width().unwrap() - } - - /// Name of the generated Rust getter for this bitfield. - /// - /// Panics if called before assigning bitfield accessor names or if - /// this bitfield have no name. - pub fn getter_name(&self) -> &str { - assert!(self.name().is_some(), "`Bitfield::getter_name` called on anonymous field"); - self.getter_name.as_ref().expect( - "`Bitfield::getter_name` should only be called after\ - assigning bitfield accessor names", - ) - } - - /// Name of the generated Rust setter for this bitfield. - /// - /// Panics if called before assigning bitfield accessor names or if - /// this bitfield have no name. - pub fn setter_name(&self) -> &str { - assert!(self.name().is_some(), "`Bitfield::setter_name` called on anonymous field"); - self.setter_name.as_ref().expect( - "`Bitfield::setter_name` should only be called\ - after assigning bitfield accessor names", - ) - } -} - -impl FieldMethods for Bitfield { - fn name(&self) -> Option<&str> { - self.data.name() - } - - fn ty(&self) -> TypeId { - self.data.ty() - } - - fn comment(&self) -> Option<&str> { - self.data.comment() - } - - fn bitfield_width(&self) -> Option { - self.data.bitfield_width() - } - - fn is_mutable(&self) -> bool { - self.data.is_mutable() - } - - fn annotations(&self) -> &Annotations { - self.data.annotations() - } - - fn offset(&self) -> Option { - self.data.offset() - } -} - - -/// A raw field might be either of a plain data member or a bitfield within a -/// bitfield allocation unit, but we haven't processed it and determined which -/// yet (which would involve allocating it into a bitfield unit if it is a -/// bitfield). -#[derive(Debug)] -struct RawField(FieldData); - -impl RawField { - /// Construct a new `RawField`. - fn new( - name: Option, - ty: TypeId, - comment: Option, - annotations: Option, - bitfield_width: Option, - mutable: bool, - offset: Option, - ) -> RawField { - RawField(FieldData { - name, - ty, - comment, - annotations: annotations.unwrap_or_default(), - bitfield_width, - mutable, - offset, - }) - } -} - -impl FieldMethods for RawField { - fn name(&self) -> Option<&str> { - self.0.name() - } - - fn ty(&self) -> TypeId { - self.0.ty() - } - - fn comment(&self) -> Option<&str> { - self.0.comment() - } - - fn bitfield_width(&self) -> Option { - self.0.bitfield_width() - } - - fn is_mutable(&self) -> bool { - self.0.is_mutable() - } - - fn annotations(&self) -> &Annotations { - self.0.annotations() - } - - fn offset(&self) -> Option { - self.0.offset() - } -} - -/// Convert the given ordered set of raw fields into a list of either plain data -/// members, and/or bitfield units containing multiple bitfields. -/// -/// If we do not have the layout for a bitfield's type, then we can't reliably -/// compute its allocation unit. In such cases, we return an error. -fn raw_fields_to_fields_and_bitfield_units( - ctx: &BindgenContext, - raw_fields: I, -) -> Result, ()> -where - I: IntoIterator, -{ - let mut raw_fields = raw_fields.into_iter().fuse().peekable(); - let mut fields = vec![]; - let mut bitfield_unit_count = 0; - - loop { - // While we have plain old data members, just keep adding them to our - // resulting fields. We introduce a scope here so that we can use - // `raw_fields` again after the `by_ref` iterator adaptor is dropped. - { - let non_bitfields = raw_fields - .by_ref() - .peeking_take_while(|f| f.bitfield_width().is_none()) - .map(|f| Field::DataMember(f.0)); - fields.extend(non_bitfields); - } - - // Now gather all the consecutive bitfields. Only consecutive bitfields - // may potentially share a bitfield allocation unit with each other in - // the Itanium C++ ABI. - let mut bitfields = raw_fields - .by_ref() - .peeking_take_while(|f| f.bitfield_width().is_some()) - .peekable(); - - if bitfields.peek().is_none() { - break; - } - - bitfields_to_allocation_units( - ctx, - &mut bitfield_unit_count, - &mut fields, - bitfields, - )?; - } - - assert!( - raw_fields.next().is_none(), - "The above loop should consume all items in `raw_fields`" - ); - - Ok(fields) -} - -/// Given a set of contiguous raw bitfields, group and allocate them into -/// (potentially multiple) bitfield units. -fn bitfields_to_allocation_units( - ctx: &BindgenContext, - bitfield_unit_count: &mut usize, - fields: &mut E, - raw_bitfields: I, -) -> Result<(), ()> -where - E: Extend, - I: IntoIterator, -{ - assert!(ctx.collected_typerefs()); - - // NOTE: What follows is reverse-engineered from LLVM's - // lib/AST/RecordLayoutBuilder.cpp - // - // FIXME(emilio): There are some differences between Microsoft and the - // Itanium ABI, but we'll ignore those and stick to Itanium for now. - // - // Also, we need to handle packed bitfields and stuff. - // - // TODO(emilio): Take into account C++'s wide bitfields, and - // packing, sigh. - - fn flush_allocation_unit( - fields: &mut E, - bitfield_unit_count: &mut usize, - unit_size_in_bits: usize, - unit_align_in_bits: usize, - bitfields: Vec, - ) where - E: Extend, - { - *bitfield_unit_count += 1; - let align = bytes_from_bits_pow2(unit_align_in_bits); - let size = align_to(unit_size_in_bits, align * 8) / 8; - let layout = Layout::new(size, align); - fields.extend(Some(Field::Bitfields(BitfieldUnit { - nth: *bitfield_unit_count, - layout: layout, - bitfields: bitfields, - }))); - } - - let mut max_align = 0; - let mut unfilled_bits_in_unit = 0; - let mut unit_size_in_bits = 0; - let mut unit_align = 0; - let mut bitfields_in_unit = vec![]; - - // TODO(emilio): Determine this from attributes or pragma ms_struct - // directives. Also, perhaps we should check if the target is MSVC? - const is_ms_struct: bool = false; - - for bitfield in raw_bitfields { - let bitfield_width = bitfield.bitfield_width().unwrap() as usize; - let bitfield_layout = ctx.resolve_type(bitfield.ty()) - .layout(ctx) - .ok_or(())?; - let bitfield_size = bitfield_layout.size; - let bitfield_align = bitfield_layout.align; - - let mut offset = unit_size_in_bits; - if is_ms_struct { - if unit_size_in_bits != 0 && - (bitfield_width == 0 || - bitfield_width > unfilled_bits_in_unit) - { - // We've reached the end of this allocation unit, so flush it - // and its bitfields. - unit_size_in_bits = align_to(unit_size_in_bits, unit_align * 8); - flush_allocation_unit( - fields, - bitfield_unit_count, - unit_size_in_bits, - unit_align, - mem::replace(&mut bitfields_in_unit, vec![]), - ); - - // Now we're working on a fresh bitfield allocation unit, so reset - // the current unit size and alignment. - offset = 0; - unit_align = 0; - } - } else { - if offset != 0 && - (bitfield_width == 0 || - (offset & (bitfield_align * 8 - 1)) + bitfield_width > - bitfield_size * 8) - { - offset = align_to(offset, bitfield_align * 8); - } - } - - // According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not - // affect the alignment of a structure or union". This makes sense: such - // bit-fields are only used for padding, and we can't perform an - // un-aligned read of something we can't read because we can't even name - // it. - if bitfield.name().is_some() { - max_align = cmp::max(max_align, bitfield_align); - - // NB: The `bitfield_width` here is completely, absolutely - // intentional. Alignment of the allocation unit is based on the - // maximum bitfield width, not (directly) on the bitfields' types' - // alignment. - unit_align = cmp::max(unit_align, bitfield_width); - } - - // Always keep all bitfields around. While unnamed bitifields are used - // for padding (and usually not needed hereafter), large unnamed - // bitfields over their types size cause weird allocation size behavior from clang. - // Therefore, all bitfields needed to be kept around in order to check for this - // and make the struct opaque in this case - bitfields_in_unit.push(Bitfield::new(offset, bitfield)); - - unit_size_in_bits = offset + bitfield_width; - - // Compute what the physical unit's final size would be given what we - // have seen so far, and use that to compute how many bits are still - // available in the unit. - let data_size = align_to(unit_size_in_bits, bitfield_align * 8); - unfilled_bits_in_unit = data_size - unit_size_in_bits; - } - - if unit_size_in_bits != 0 { - // Flush the last allocation unit and its bitfields. - flush_allocation_unit( - fields, - bitfield_unit_count, - unit_size_in_bits, - unit_align, - bitfields_in_unit, - ); - } - - Ok(()) -} - -/// A compound structure's fields are initially raw, and have bitfields that -/// have not been grouped into allocation units. During this time, the fields -/// are mutable and we build them up during parsing. -/// -/// Then, once resolving typerefs is completed, we compute all structs' fields' -/// bitfield allocation units, and they remain frozen and immutable forever -/// after. -#[derive(Debug)] -enum CompFields { - BeforeComputingBitfieldUnits(Vec), - AfterComputingBitfieldUnits(Vec), - ErrorComputingBitfieldUnits, -} - -impl Default for CompFields { - fn default() -> CompFields { - CompFields::BeforeComputingBitfieldUnits(vec![]) - } -} - -impl CompFields { - fn append_raw_field(&mut self, raw: RawField) { - match *self { - CompFields::BeforeComputingBitfieldUnits(ref mut raws) => { - raws.push(raw); - } - _ => { - panic!( - "Must not append new fields after computing bitfield allocation units" - ); - } - } - } - - fn compute_bitfield_units(&mut self, ctx: &BindgenContext) { - let raws = match *self { - CompFields::BeforeComputingBitfieldUnits(ref mut raws) => { - mem::replace(raws, vec![]) - } - _ => { - panic!("Already computed bitfield units"); - } - }; - - let result = - raw_fields_to_fields_and_bitfield_units(ctx, raws); - - match result { - Ok(fields_and_units) => { - mem::replace( - self, - CompFields::AfterComputingBitfieldUnits(fields_and_units)); - } - Err(()) => { - mem::replace( - self, - CompFields::ErrorComputingBitfieldUnits - ); - } - } - } - - fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) { - let fields = match *self { - CompFields::AfterComputingBitfieldUnits(ref mut fields) => fields, - CompFields::ErrorComputingBitfieldUnits => { - // Nothing to do here. - return; - } - CompFields::BeforeComputingBitfieldUnits(_) => { - panic!("Not yet computed bitfield units."); - } - }; - - fn has_method(methods: &[Method], ctx: &BindgenContext, name: &str) -> bool { - methods.iter().any(|method| { - let method_name = ctx.resolve_func(method.signature()).name(); - method_name == name || ctx.rust_mangle(&method_name) == name - }) - } - - struct AccessorNamesPair { - getter: String, - setter: String, - } - - let mut accessor_names: HashMap = fields - .iter() - .flat_map(|field| match *field { - Field::Bitfields(ref bu) => &*bu.bitfields, - Field::DataMember(_) => &[], - }) - .filter_map(|bitfield| bitfield.name()) - .map(|bitfield_name| { - let bitfield_name = bitfield_name.to_string(); - let getter = { - let mut getter = ctx.rust_mangle(&bitfield_name).to_string(); - if has_method(methods, ctx, &getter) { - getter.push_str("_bindgen_bitfield"); - } - getter - }; - let setter = { - let setter = format!("set_{}", bitfield_name); - let mut setter = ctx.rust_mangle(&setter).to_string(); - if has_method(methods, ctx, &setter) { - setter.push_str("_bindgen_bitfield"); - } - setter - }; - (bitfield_name, AccessorNamesPair { getter, setter }) - }) - .collect(); - - let mut anon_field_counter = 0; - for field in fields.iter_mut() { - match *field { - Field::DataMember(FieldData { ref mut name, .. }) => { - if let Some(_) = *name { - continue; - } - - anon_field_counter += 1; - let generated_name = format!("__bindgen_anon_{}", anon_field_counter); - *name = Some(generated_name); - } - Field::Bitfields(ref mut bu) => for bitfield in &mut bu.bitfields { - if bitfield.name().is_none() { - continue; - } - - if let Some(AccessorNamesPair { getter, setter }) = - accessor_names.remove(bitfield.name().unwrap()) - { - bitfield.getter_name = Some(getter); - bitfield.setter_name = Some(setter); - } - }, - } - } - } -} - -impl Trace for CompFields { - type Extra = (); - - fn trace(&self, context: &BindgenContext, tracer: &mut T, _: &()) - where - T: Tracer, - { - match *self { - CompFields::ErrorComputingBitfieldUnits => {} - CompFields::BeforeComputingBitfieldUnits(ref fields) => { - for f in fields { - tracer.visit_kind(f.ty().into(), EdgeKind::Field); - } - } - CompFields::AfterComputingBitfieldUnits(ref fields) => { - for f in fields { - f.trace(context, tracer, &()); - } - } - } - } -} - -/// Common data shared across different field types. -#[derive(Clone, Debug)] -pub struct FieldData { - /// The name of the field, empty if it's an unnamed bitfield width. - name: Option, - - /// The inner type. - ty: TypeId, - - /// The doc comment on the field if any. - comment: Option, - - /// Annotations for this field, or the default. - annotations: Annotations, - - /// If this field is a bitfield, and how many bits does it contain if it is. - bitfield_width: Option, - - /// If the C++ field is marked as `mutable` - mutable: bool, - - /// The offset of the field (in bits) - offset: Option, -} - -impl FieldMethods for FieldData { - fn name(&self) -> Option<&str> { - self.name.as_ref().map(|n| &**n) - } - - fn ty(&self) -> TypeId { - self.ty - } - - fn comment(&self) -> Option<&str> { - self.comment.as_ref().map(|c| &**c) - } - - fn bitfield_width(&self) -> Option { - self.bitfield_width - } - - fn is_mutable(&self) -> bool { - self.mutable - } - - fn annotations(&self) -> &Annotations { - &self.annotations - } - - fn offset(&self) -> Option { - self.offset - } -} - -/// The kind of inheritance a base class is using. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum BaseKind { - /// Normal inheritance, like: - /// - /// ```cpp - /// class A : public B {}; - /// ``` - Normal, - /// Virtual inheritance, like: - /// - /// ```cpp - /// class A: public virtual B {}; - /// ``` - Virtual, -} - -/// A base class. -#[derive(Clone, Debug)] -pub struct Base { - /// The type of this base class. - pub ty: TypeId, - /// The kind of inheritance we're doing. - pub kind: BaseKind, - /// Name of the field in which this base should be stored. - pub field_name: String, -} - -impl Base { - /// Whether this base class is inheriting virtually. - pub fn is_virtual(&self) -> bool { - self.kind == BaseKind::Virtual - } - - /// Whether this base class should have it's own field for storage. - pub fn requires_storage(&self, ctx: &BindgenContext) -> bool { - // Virtual bases are already taken into account by the vtable - // pointer. - // - // FIXME(emilio): Is this always right? - if self.is_virtual() { - return false; - } - - // NB: We won't include zero-sized types in our base chain because they - // would contribute to our size given the dummy field we insert for - // zero-sized types. - if self.ty.is_zero_sized(ctx) { - return false; - } - - true - } -} - -/// A compound type. -/// -/// Either a struct or union, a compound type is built up from the combination -/// of fields which also are associated with their own (potentially compound) -/// type. -#[derive(Debug)] -pub struct CompInfo { - /// Whether this is a struct or a union. - kind: CompKind, - - /// The members of this struct or union. - fields: CompFields, - - /// The abstract template parameters of this class. Note that these are NOT - /// concrete template arguments, and should always be a - /// `Type(TypeKind::TypeParam(name))`. For concrete template arguments, see - /// `TypeKind::TemplateInstantiation`. - template_params: Vec, - - /// The method declarations inside this class, if in C++ mode. - methods: Vec, - - /// The different constructors this struct or class contains. - constructors: Vec, - - /// The destructor of this type. The bool represents whether this destructor - /// is virtual. - destructor: Option<(MethodKind, FunctionId)>, - - /// Vector of classes this one inherits from. - base_members: Vec, - - /// The inner types that were declared inside this class, in something like: - /// - /// class Foo { - /// typedef int FooTy; - /// struct Bar { - /// int baz; - /// }; - /// } - /// - /// static Foo::Bar const = {3}; - inner_types: Vec, - - /// Set of static constants declared inside this class. - inner_vars: Vec, - - /// Whether this type should generate an vtable (TODO: Should be able to - /// look at the virtual methods and ditch this field). - has_own_virtual_method: bool, - - /// Whether this type has destructor. - has_destructor: bool, - - /// Whether this type has a base type with more than one member. - /// - /// TODO: We should be able to compute this. - has_nonempty_base: bool, - - /// If this type has a template parameter which is not a type (e.g.: a - /// size_t) - has_non_type_template_params: bool, - - /// Whether we saw `__attribute__((packed))` on or within this type. - packed_attr: bool, - - /// Used to know if we've found an opaque attribute that could cause us to - /// generate a type with invalid layout. This is explicitly used to avoid us - /// generating bad alignments when parsing types like max_align_t. - /// - /// It's not clear what the behavior should be here, if generating the item - /// and pray, or behave as an opaque type. - found_unknown_attr: bool, - - /// Used to indicate when a struct has been forward declared. Usually used - /// in headers so that APIs can't modify them directly. - is_forward_declaration: bool, -} - -impl CompInfo { - /// Construct a new compound type. - pub fn new(kind: CompKind) -> Self { - CompInfo { - kind: kind, - fields: CompFields::default(), - template_params: vec![], - methods: vec![], - constructors: vec![], - destructor: None, - base_members: vec![], - inner_types: vec![], - inner_vars: vec![], - has_own_virtual_method: false, - has_destructor: false, - has_nonempty_base: false, - has_non_type_template_params: false, - packed_attr: false, - found_unknown_attr: false, - is_forward_declaration: false, - } - } - - /// Compute the layout of this type. - /// - /// This is called as a fallback under some circumstances where LLVM doesn't - /// give us the correct layout. - /// - /// If we're a union without known layout, we try to compute it from our - /// members. This is not ideal, but clang fails to report the size for these - /// kind of unions, see test/headers/template_union.hpp - pub fn layout(&self, ctx: &BindgenContext) -> Option { - use std::cmp; - - // We can't do better than clang here, sorry. - if self.kind == CompKind::Struct { - return None; - } - - let mut max_size = 0; - let mut max_align = 0; - for field in self.fields() { - let field_layout = field.layout(ctx); - - if let Some(layout) = field_layout { - max_size = cmp::max(max_size, layout.size); - max_align = cmp::max(max_align, layout.align); - } - } - - Some(Layout::new(max_size, max_align)) - } - - /// Get this type's set of fields. - pub fn fields(&self) -> &[Field] { - match self.fields { - CompFields::ErrorComputingBitfieldUnits => &[], - CompFields::AfterComputingBitfieldUnits(ref fields) => fields, - CompFields::BeforeComputingBitfieldUnits(_) => { - panic!("Should always have computed bitfield units first"); - } - } - } - - /// Does this type have any template parameters that aren't types - /// (e.g. int)? - pub fn has_non_type_template_params(&self) -> bool { - self.has_non_type_template_params - } - - /// Do we see a virtual function during parsing? - /// Get the has_own_virtual_method boolean. - pub fn has_own_virtual_method(&self) -> bool { - return self.has_own_virtual_method; - } - - /// Did we see a destructor when parsing this type? - pub fn has_own_destructor(&self) -> bool { - self.has_destructor - } - - /// Get this type's set of methods. - pub fn methods(&self) -> &[Method] { - &self.methods - } - - /// Get this type's set of constructors. - pub fn constructors(&self) -> &[FunctionId] { - &self.constructors - } - - /// Get this type's destructor. - pub fn destructor(&self) -> Option<(MethodKind, FunctionId)> { - self.destructor - } - - /// What kind of compound type is this? - pub fn kind(&self) -> CompKind { - self.kind - } - - /// Is this a union? - pub fn is_union(&self) -> bool { - self.kind() == CompKind::Union - } - - /// The set of types that this one inherits from. - pub fn base_members(&self) -> &[Base] { - &self.base_members - } - - /// Construct a new compound type from a Clang type. - pub fn from_ty( - potential_id: ItemId, - ty: &clang::Type, - location: Option, - ctx: &mut BindgenContext, - ) -> Result { - use clang_sys::*; - assert!( - ty.template_args().is_none(), - "We handle template instantiations elsewhere" - ); - - let mut cursor = ty.declaration(); - let mut kind = Self::kind_from_cursor(&cursor); - if kind.is_err() { - if let Some(location) = location { - kind = Self::kind_from_cursor(&location); - cursor = location; - } - } - - let kind = kind?; - - debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor); - - let mut ci = CompInfo::new(kind); - ci.is_forward_declaration = - location.map_or(true, |cur| match cur.kind() { - CXCursor_StructDecl | - CXCursor_UnionDecl | - CXCursor_ClassDecl => !cur.is_definition(), - _ => false, - }); - - let mut maybe_anonymous_struct_field = None; - cursor.visit(|cur| { - if cur.kind() != CXCursor_FieldDecl { - if let Some((ty, clang_ty, offset)) = - maybe_anonymous_struct_field.take() { - if cur.kind() == CXCursor_TypedefDecl && - cur.typedef_type().unwrap().canonical_type() == clang_ty { - // Typedefs of anonymous structs appear later in the ast - // than the struct itself, that would otherwise be an - // anonymous field. Detect that case here, and do - // nothing. - } else { - let field = - RawField::new(None, ty, None, None, None, false, offset); - ci.fields.append_raw_field(field); - } - } - } - - match cur.kind() { - CXCursor_FieldDecl => { - if let Some((ty, clang_ty, offset)) = - maybe_anonymous_struct_field.take() { - let mut used = false; - cur.visit(|child| { - if child.cur_type() == clang_ty { - used = true; - } - CXChildVisit_Continue - }); - if !used { - let field = RawField::new(None, - ty, - None, - None, - None, - false, - offset); - ci.fields.append_raw_field(field); - } - } - - let bit_width = cur.bit_width(); - let field_type = Item::from_ty_or_ref(cur.cur_type(), - cur, - Some(potential_id), - ctx); - - let comment = cur.raw_comment(); - let annotations = Annotations::new(&cur); - let name = cur.spelling(); - let is_mutable = cursor.is_mutable_field(); - let offset = cur.offset_of_field().ok(); - - // Name can be empty if there are bitfields, for example, - // see tests/headers/struct_with_bitfields.h - assert!(!name.is_empty() || bit_width.is_some(), - "Empty field name?"); - - let name = if name.is_empty() { None } else { Some(name) }; - - let field = RawField::new(name, - field_type, - comment, - annotations, - bit_width, - is_mutable, - offset); - ci.fields.append_raw_field(field); - - // No we look for things like attributes and stuff. - cur.visit(|cur| { - if cur.kind() == CXCursor_UnexposedAttr { - ci.found_unknown_attr = true; - } - CXChildVisit_Continue - }); - - } - CXCursor_UnexposedAttr => { - ci.found_unknown_attr = true; - } - CXCursor_EnumDecl | - CXCursor_TypeAliasDecl | - CXCursor_TypeAliasTemplateDecl | - CXCursor_TypedefDecl | - CXCursor_StructDecl | - CXCursor_UnionDecl | - CXCursor_ClassTemplate | - CXCursor_ClassDecl => { - // We can find non-semantic children here, clang uses a - // StructDecl to note incomplete structs that haven't been - // forward-declared before, see [1]. - // - // Also, clang seems to scope struct definitions inside - // unions, and other named struct definitions inside other - // structs to the whole translation unit. - // - // Let's just assume that if the cursor we've found is a - // definition, it's a valid inner type. - // - // [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/482 - let is_inner_struct = cur.semantic_parent() == cursor || - cur.is_definition(); - if !is_inner_struct { - return CXChildVisit_Continue; - } - - // Even if this is a definition, we may not be the semantic - // parent, see #1281. - let inner = Item::parse(cur, Some(potential_id), ctx) - .expect("Inner ClassDecl"); - - let inner = inner.expect_type_id(ctx); - - ci.inner_types.push(inner); - - // A declaration of an union or a struct without name could - // also be an unnamed field, unfortunately. - if cur.spelling().is_empty() && - cur.kind() != CXCursor_EnumDecl { - let ty = cur.cur_type(); - let offset = cur.offset_of_field().ok(); - maybe_anonymous_struct_field = Some((inner, ty, offset)); - } - } - CXCursor_PackedAttr => { - ci.packed_attr = true; - } - CXCursor_TemplateTypeParameter => { - let param = Item::type_param(None, cur, ctx) - .expect("Item::type_param should't fail when pointing \ - at a TemplateTypeParameter"); - ci.template_params.push(param); - } - CXCursor_CXXBaseSpecifier => { - let is_virtual_base = cur.is_virtual_base(); - ci.has_own_virtual_method |= is_virtual_base; - - let kind = if is_virtual_base { - BaseKind::Virtual - } else { - BaseKind::Normal - }; - - let field_name = match ci.base_members.len() { - 0 => "_base".into(), - n => format!("_base_{}", n), - }; - let type_id = - Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx); - ci.base_members.push(Base { - ty: type_id, - kind: kind, - field_name: field_name, - }); - } - CXCursor_Constructor | - CXCursor_Destructor | - CXCursor_CXXMethod => { - let is_virtual = cur.method_is_virtual(); - let is_static = cur.method_is_static(); - debug_assert!(!(is_static && is_virtual), "How?"); - - ci.has_destructor |= cur.kind() == CXCursor_Destructor; - ci.has_own_virtual_method |= is_virtual; - - // This used to not be here, but then I tried generating - // stylo bindings with this (without path filters), and - // cried a lot with a method in gfx/Point.h - // (ToUnknownPoint), that somehow was causing the same type - // to be inserted in the map two times. - // - // I couldn't make a reduced test case, but anyway... - // Methods of template functions not only use to be inlined, - // but also instantiated, and we wouldn't be able to call - // them, so just bail out. - if !ci.template_params.is_empty() { - return CXChildVisit_Continue; - } - - // NB: This gets us an owned `Function`, not a - // `FunctionSig`. - let signature = - match Item::parse(cur, Some(potential_id), ctx) { - Ok(item) if ctx.resolve_item(item) - .kind() - .is_function() => item, - _ => return CXChildVisit_Continue, - }; - - let signature = signature.expect_function_id(ctx); - - match cur.kind() { - CXCursor_Constructor => { - ci.constructors.push(signature); - } - CXCursor_Destructor => { - let kind = if is_virtual { - MethodKind::VirtualDestructor { - pure_virtual: cur.method_is_pure_virtual(), - } - } else { - MethodKind::Destructor - }; - ci.destructor = Some((kind, signature)); - } - CXCursor_CXXMethod => { - let is_const = cur.method_is_const(); - let method_kind = if is_static { - MethodKind::Static - } else if is_virtual { - MethodKind::Virtual { - pure_virtual: cur.method_is_pure_virtual(), - } - } else { - MethodKind::Normal - }; - - let method = - Method::new(method_kind, signature, is_const); - - ci.methods.push(method); - } - _ => unreachable!("How can we see this here?"), - } - } - CXCursor_NonTypeTemplateParameter => { - ci.has_non_type_template_params = true; - } - CXCursor_VarDecl => { - let linkage = cur.linkage(); - if linkage != CXLinkage_External && - linkage != CXLinkage_UniqueExternal { - return CXChildVisit_Continue; - } - - let visibility = cur.visibility(); - if visibility != CXVisibility_Default { - return CXChildVisit_Continue; - } - - if let Ok(item) = Item::parse(cur, - Some(potential_id), - ctx) { - ci.inner_vars.push(item.as_var_id_unchecked()); - } - } - // Intentionally not handled - CXCursor_CXXAccessSpecifier | - CXCursor_CXXFinalAttr | - CXCursor_FunctionTemplate | - CXCursor_ConversionFunction => {} - _ => { - warn!("unhandled comp member `{}` (kind {:?}) in `{}` ({})", - cur.spelling(), - clang::kind_to_str(cur.kind()), - cursor.spelling(), - cur.location()); - } - } - CXChildVisit_Continue - }); - - if let Some((ty, _, offset)) = maybe_anonymous_struct_field { - let field = - RawField::new(None, ty, None, None, None, false, offset); - ci.fields.append_raw_field(field); - } - - Ok(ci) - } - - fn kind_from_cursor( - cursor: &clang::Cursor, - ) -> Result { - use clang_sys::*; - Ok(match cursor.kind() { - CXCursor_UnionDecl => CompKind::Union, - CXCursor_ClassDecl | - CXCursor_StructDecl => CompKind::Struct, - CXCursor_CXXBaseSpecifier | - CXCursor_ClassTemplatePartialSpecialization | - CXCursor_ClassTemplate => { - match cursor.template_kind() { - CXCursor_UnionDecl => CompKind::Union, - _ => CompKind::Struct, - } - } - _ => { - warn!("Unknown kind for comp type: {:?}", cursor); - return Err(ParseError::Continue); - } - }) - } - - /// Get the set of types that were declared within this compound type - /// (e.g. nested class definitions). - pub fn inner_types(&self) -> &[TypeId] { - &self.inner_types - } - - /// Get the set of static variables declared within this compound type. - pub fn inner_vars(&self) -> &[VarId] { - &self.inner_vars - } - - /// Have we found a field with an opaque type that could potentially mess up - /// the layout of this compound type? - pub fn found_unknown_attr(&self) -> bool { - self.found_unknown_attr - } - - /// Is this compound type packed? - pub fn is_packed(&self, ctx: &BindgenContext, layout: &Option) -> bool { - if self.packed_attr { - return true - } - - // Even though `libclang` doesn't expose `#pragma packed(...)`, we can - // detect it through its effects. - if let Some(ref parent_layout) = *layout { - if self.fields().iter().any(|f| match *f { - Field::Bitfields(ref unit) => { - unit.layout().align > parent_layout.align - } - Field::DataMember(ref data) => { - let field_ty = ctx.resolve_type(data.ty()); - field_ty.layout(ctx).map_or(false, |field_ty_layout| { - field_ty_layout.align > parent_layout.align - }) - } - }) { - info!("Found a struct that was defined within `#pragma packed(...)`"); - return true; - } - } - - false - } - - /// Returns true if compound type has been forward declared - pub fn is_forward_declaration(&self) -> bool { - self.is_forward_declaration - } - - /// Compute this compound structure's bitfield allocation units. - pub fn compute_bitfield_units(&mut self, ctx: &BindgenContext) { - self.fields.compute_bitfield_units(ctx); - } - - /// Assign for each anonymous field a generated name. - pub fn deanonymize_fields(&mut self, ctx: &BindgenContext) { - self.fields.deanonymize_fields(ctx, &self.methods); - } - - /// Returns whether the current union can be represented as a Rust `union` - /// - /// Requirements: - /// 1. Current RustTarget allows for `untagged_union` - /// 2. Each field can derive `Copy` - pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool { - if !ctx.options().rust_features().untagged_union { - return false; - } - - if self.is_forward_declaration() { - return false; - } - - self.fields().iter().all(|f| match *f { - Field::DataMember(ref field_data) => { - field_data.ty().can_derive_copy(ctx) - } - Field::Bitfields(_) => true, - }) - } -} - -impl DotAttributes for CompInfo { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!(out, "CompKind{:?}", self.kind)?; - - if self.has_own_virtual_method { - writeln!(out, "has_vtabletrue")?; - } - - if self.has_destructor { - writeln!(out, "has_destructortrue")?; - } - - if self.has_nonempty_base { - writeln!(out, "has_nonempty_basetrue")?; - } - - if self.has_non_type_template_params { - writeln!( - out, - "has_non_type_template_paramstrue" - )?; - } - - if self.packed_attr { - writeln!(out, "packed_attrtrue")?; - } - - if self.is_forward_declaration { - writeln!( - out, - "is_forward_declarationtrue" - )?; - } - - if !self.fields().is_empty() { - writeln!(out, r#"fields"#)?; - for field in self.fields() { - field.dot_attributes(ctx, out)?; - } - writeln!(out, "
")?; - } - - Ok(()) - } -} - -impl IsOpaque for CompInfo { - type Extra = Option; - - fn is_opaque(&self, ctx: &BindgenContext, layout: &Option) -> bool { - if self.has_non_type_template_params { - return true - } - - // When we do not have the layout for a bitfield's type (for example, it - // is a type parameter), then we can't compute bitfield units. We are - // left with no choice but to make the whole struct opaque, or else we - // might generate structs with incorrect sizes and alignments. - if let CompFields::ErrorComputingBitfieldUnits = self.fields { - return true; - } - - // Bitfields with a width that is larger than their unit's width have - // some strange things going on, and the best we can do is make the - // whole struct opaque. - if self.fields().iter().any(|f| match *f { - Field::DataMember(_) => { - false - }, - Field::Bitfields(ref unit) => { - unit.bitfields().iter().any(|bf| { - let bitfield_layout = ctx.resolve_type(bf.ty()) - .layout(ctx) - .expect("Bitfield without layout? Gah!"); - bf.width() / 8 > bitfield_layout.size as u32 - }) - } - }) { - return true; - } - - // We don't have `#[repr(packed = "N")]` in Rust yet, so the best we can - // do is make this struct opaque. - // - // See https://github.com/rust-lang-nursery/rust-bindgen/issues/537 and - // https://github.com/rust-lang/rust/issues/33158 - if self.is_packed(ctx, layout) && layout.map_or(false, |l| l.align > 1) { - warn!("Found a type that is both packed and aligned to greater than \ - 1; Rust doesn't have `#[repr(packed = \"N\")]` yet, so we \ - are treating it as opaque"); - return true; - } - - false - } -} - -impl TemplateParameters for CompInfo { - fn self_template_params( - &self, - _ctx: &BindgenContext, - ) -> Option> { - if self.template_params.is_empty() { - None - } else { - Some(self.template_params.clone()) - } - } -} - -impl Trace for CompInfo { - type Extra = Item; - - fn trace(&self, context: &BindgenContext, tracer: &mut T, item: &Item) - where - T: Tracer, - { - let params = item.all_template_params(context).unwrap_or(vec![]); - for p in params { - tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition); - } - - for ty in self.inner_types() { - tracer.visit_kind(ty.into(), EdgeKind::InnerType); - } - - for &var in self.inner_vars() { - tracer.visit_kind(var.into(), EdgeKind::InnerVar); - } - - for method in self.methods() { - tracer.visit_kind(method.signature.into(), EdgeKind::Method); - } - - if let Some((_kind, signature)) = self.destructor() { - tracer.visit_kind(signature.into(), EdgeKind::Destructor); - } - - for ctor in self.constructors() { - tracer.visit_kind(ctor.into(), EdgeKind::Constructor); - } - - // Base members and fields are not generated for opaque types (but all - // of the above things are) so stop here. - if item.is_opaque(context, &()) { - return; - } - - for base in self.base_members() { - tracer.visit_kind(base.ty.into(), EdgeKind::BaseMember); - } - - self.fields.trace(context, tracer, &()); - } -} diff --git a/src/ir/context.rs b/src/ir/context.rs deleted file mode 100644 index 58a90ba6bb..0000000000 --- a/src/ir/context.rs +++ /dev/null @@ -1,2680 +0,0 @@ -//! Common context that is passed around during parsing and codegen. - -use super::analysis::{CannotDeriveCopy, CannotDeriveDebug, CannotDeriveDefault, - CannotDeriveHash, CannotDerivePartialEqOrPartialOrd, - HasTypeParameterInArray, HasVtableAnalysis, - HasVtableResult, HasDestructorAnalysis, - UsedTemplateParameters, HasFloat, SizednessAnalysis, - SizednessResult, analyze}; -use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, - CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq, CanDerive}; -use super::int::IntKind; -use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath, ItemSet}; -use super::item_kind::ItemKind; -use super::module::{Module, ModuleKind}; -use super::template::{TemplateInstantiation, TemplateParameters}; -use super::traversal::{self, Edge, ItemTraversal}; -use super::ty::{FloatKind, Type, TypeKind}; -use super::function::Function; -use super::super::time::Timer; -use BindgenOptions; -use callbacks::ParseCallbacks; -use cexpr; -use clang::{self, Cursor}; -use clang_sys; -use parse::ClangItemParser; -use proc_macro2::{Term, Span}; -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::{HashMap, HashSet, hash_map}; -use std::collections::btree_map::{self, BTreeMap}; -use std::iter::IntoIterator; -use std::mem; - -/// An identifier for some kind of IR item. -#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)] -pub struct ItemId(usize); - -macro_rules! item_id_newtype { - ( - $( #[$attr:meta] )* - pub struct $name:ident(ItemId) - where - $( #[$checked_attr:meta] )* - checked = $checked:ident with $check_method:ident, - $( #[$expected_attr:meta] )* - expected = $expected:ident, - $( #[$unchecked_attr:meta] )* - unchecked = $unchecked:ident; - ) => { - $( #[$attr] )* - #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)] - pub struct $name(ItemId); - - impl $name { - /// Create an `ItemResolver` from this id. - pub fn into_resolver(self) -> ItemResolver { - let id: ItemId = self.into(); - id.into() - } - } - - impl ::std::cmp::PartialEq for $name - where - T: Copy + Into - { - fn eq(&self, rhs: &T) -> bool { - let rhs: ItemId = (*rhs).into(); - self.0 == rhs - } - } - - impl From<$name> for ItemId { - fn from(id: $name) -> ItemId { - id.0 - } - } - - impl<'a> From<&'a $name> for ItemId { - fn from(id: &'a $name) -> ItemId { - id.0 - } - } - - impl ItemId { - $( #[$checked_attr] )* - pub fn $checked(&self, ctx: &BindgenContext) -> Option<$name> { - if ctx.resolve_item(*self).kind().$check_method() { - Some($name(*self)) - } else { - None - } - } - - $( #[$expected_attr] )* - pub fn $expected(&self, ctx: &BindgenContext) -> $name { - self.$checked(ctx) - .expect(concat!( - stringify!($expected), - " called with ItemId that points to the wrong ItemKind" - )) - } - - $( #[$unchecked_attr] )* - pub fn $unchecked(&self) -> $name { - $name(*self) - } - } - } -} - -item_id_newtype! { - /// An identifier for an `Item` whose `ItemKind` is known to be - /// `ItemKind::Type`. - pub struct TypeId(ItemId) - where - /// Convert this `ItemId` into a `TypeId` if its associated item is a type, - /// otherwise return `None`. - checked = as_type_id with is_type, - - /// Convert this `ItemId` into a `TypeId`. - /// - /// If this `ItemId` does not point to a type, then panic. - expected = expect_type_id, - - /// Convert this `ItemId` into a `TypeId` without actually checking whether - /// this id actually points to a `Type`. - unchecked = as_type_id_unchecked; -} - -item_id_newtype! { - /// An identifier for an `Item` whose `ItemKind` is known to be - /// `ItemKind::Module`. - pub struct ModuleId(ItemId) - where - /// Convert this `ItemId` into a `ModuleId` if its associated item is a - /// module, otherwise return `None`. - checked = as_module_id with is_module, - - /// Convert this `ItemId` into a `ModuleId`. - /// - /// If this `ItemId` does not point to a module, then panic. - expected = expect_module_id, - - /// Convert this `ItemId` into a `ModuleId` without actually checking - /// whether this id actually points to a `Module`. - unchecked = as_module_id_unchecked; -} - -item_id_newtype! { - /// An identifier for an `Item` whose `ItemKind` is known to be - /// `ItemKind::Var`. - pub struct VarId(ItemId) - where - /// Convert this `ItemId` into a `VarId` if its associated item is a var, - /// otherwise return `None`. - checked = as_var_id with is_var, - - /// Convert this `ItemId` into a `VarId`. - /// - /// If this `ItemId` does not point to a var, then panic. - expected = expect_var_id, - - /// Convert this `ItemId` into a `VarId` without actually checking whether - /// this id actually points to a `Var`. - unchecked = as_var_id_unchecked; -} - -item_id_newtype! { - /// An identifier for an `Item` whose `ItemKind` is known to be - /// `ItemKind::Function`. - pub struct FunctionId(ItemId) - where - /// Convert this `ItemId` into a `FunctionId` if its associated item is a function, - /// otherwise return `None`. - checked = as_function_id with is_function, - - /// Convert this `ItemId` into a `FunctionId`. - /// - /// If this `ItemId` does not point to a function, then panic. - expected = expect_function_id, - - /// Convert this `ItemId` into a `FunctionId` without actually checking whether - /// this id actually points to a `Function`. - unchecked = as_function_id_unchecked; -} - -impl From for usize { - fn from(id: ItemId) -> usize { - id.0 - } -} - -impl ItemId { - /// Get a numeric representation of this id. - pub fn as_usize(&self) -> usize { - (*self).into() - } -} - -impl ::std::cmp::PartialEq for ItemId -where - T: Copy + Into -{ - fn eq(&self, rhs: &T) -> bool { - let rhs: ItemId = (*rhs).into(); - self.0 == rhs.0 - } -} - -impl CanDeriveDebug for T -where - T: Copy + Into -{ - fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self) - } -} - -impl CanDeriveDefault for T -where - T: Copy + Into -{ - fn can_derive_default(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_default && ctx.lookup_can_derive_default(*self) - } -} - -impl<'a, T> CanDeriveCopy<'a> for T -where - T: Copy + Into -{ - fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self) - } -} - -impl CanDeriveHash for T -where - T: Copy + Into -{ - fn can_derive_hash(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self) - } -} - -impl CanDerivePartialOrd for T -where - T: Copy + Into -{ - fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialord && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes - } -} - -impl CanDerivePartialEq for T -where - T: Copy + Into -{ - fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes - } -} - -impl CanDeriveEq for T -where - T: Copy + Into -{ - fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_eq && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes && - !ctx.lookup_has_float(*self) - } -} - -impl CanDeriveOrd for T -where - T: Copy + Into -{ - fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_ord && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes && - !ctx.lookup_has_float(*self) - } -} - -/// A key used to index a resolved type, so we only process it once. -/// -/// This is almost always a USR string (an unique identifier generated by -/// clang), but it can also be the canonical declaration if the type is unnamed, -/// in which case clang may generate the same USR for multiple nested unnamed -/// types. -#[derive(Eq, PartialEq, Hash, Debug)] -enum TypeKey { - USR(String), - Declaration(Cursor), -} - -/// A context used during parsing and generation of structs. -#[derive(Debug)] -pub struct BindgenContext { - /// The map of all the items parsed so far. - /// - /// It's a BTreeMap because we want the keys to be sorted to have consistent - /// output. - items: BTreeMap, - - /// The next item id to use during this bindings regeneration. - next_item_id: ItemId, - - /// Clang USR to type map. This is needed to be able to associate types with - /// item ids during parsing. - types: HashMap, - - /// Maps from a cursor to the item id of the named template type parameter - /// for that cursor. - type_params: HashMap, - - /// A cursor to module map. Similar reason than above. - modules: HashMap, - - /// The root module, this is guaranteed to be an item of kind Module. - root_module: ModuleId, - - /// Current module being traversed. - current_module: ModuleId, - - /// A HashMap keyed on a type definition, and whose value is the parent id - /// of the declaration. - /// - /// This is used to handle the cases where the semantic and the lexical - /// parents of the cursor differ, like when a nested class is defined - /// outside of the parent class. - semantic_parents: HashMap, - - /// A stack with the current type declarations and types we're parsing. This - /// is needed to avoid infinite recursion when parsing a type like: - /// - /// struct c { struct c* next; }; - /// - /// This means effectively, that a type has a potential ID before knowing if - /// it's a correct type. But that's not important in practice. - /// - /// We could also use the `types` HashMap, but my intention with it is that - /// only valid types and declarations end up there, and this could - /// potentially break that assumption. - currently_parsed_types: Vec, - - /// A HashSet with all the already parsed macro names. This is done to avoid - /// hard errors while parsing duplicated macros, as well to allow macro - /// expression parsing. - parsed_macros: HashMap, cexpr::expr::EvalResult>, - - /// The active replacements collected from replaces="xxx" annotations. - replacements: HashMap, ItemId>, - - collected_typerefs: bool, - - in_codegen: bool, - - /// The clang index for parsing. - index: clang::Index, - - /// The translation unit for parsing. - translation_unit: clang::TranslationUnit, - - /// Target information that can be useful for some stuff. - target_info: Option, - - /// The options given by the user via cli or other medium. - options: BindgenOptions, - - /// Whether a bindgen complex was generated - generated_bindegen_complex: Cell, - - /// The set of `ItemId`s that are whitelisted. This the very first thing - /// computed after parsing our IR, and before running any of our analyses. - whitelisted: Option, - - /// The set of `ItemId`s that are whitelisted for code generation _and_ that - /// we should generate accounting for the codegen options. - /// - /// It's computed right after computing the whitelisted items. - codegen_items: Option, - - /// Map from an item's id to the set of template parameter items that it - /// uses. See `ir::named` for more details. Always `Some` during the codegen - /// phase. - used_template_parameters: Option>, - - /// The set of `TypeKind::Comp` items found during parsing that need their - /// bitfield allocation units computed. Drained in `compute_bitfield_units`. - need_bitfield_allocation: Vec, - - /// The set of (`ItemId`s of) types that can't derive debug. - /// - /// This is populated when we enter codegen by `compute_cannot_derive_debug` - /// and is always `None` before that and `Some` after. - cannot_derive_debug: Option>, - - /// The set of (`ItemId`s of) types that can't derive default. - /// - /// This is populated when we enter codegen by `compute_cannot_derive_default` - /// and is always `None` before that and `Some` after. - cannot_derive_default: Option>, - - /// The set of (`ItemId`s of) types that can't derive copy. - /// - /// This is populated when we enter codegen by `compute_cannot_derive_copy` - /// and is always `None` before that and `Some` after. - cannot_derive_copy: Option>, - - /// The set of (`ItemId`s of) types that can't derive copy in array. - /// - /// This is populated when we enter codegen by `compute_cannot_derive_copy` - /// and is always `None` before that and `Some` after. - cannot_derive_copy_in_array: Option>, - - /// The set of (`ItemId`s of) types that can't derive hash. - /// - /// This is populated when we enter codegen by `compute_can_derive_hash` - /// and is always `None` before that and `Some` after. - cannot_derive_hash: Option>, - - /// The map why specified `ItemId`s of) types that can't derive hash. - /// - /// This is populated when we enter codegen by - /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None` - /// before that and `Some` after. - cannot_derive_partialeq_or_partialord: Option>, - - /// The sizedness of types. - /// - /// This is populated by `compute_sizedness` and is always `None` before - /// that function is invoked and `Some` afterwards. - sizedness: Option>, - - /// The set of (`ItemId's of`) types that has vtable. - /// - /// Populated when we enter codegen by `compute_has_vtable`; always `None` - /// before that and `Some` after. - have_vtable: Option>, - - /// The set of (`ItemId's of`) types that has destructor. - /// - /// Populated when we enter codegen by `compute_has_destructor`; always `None` - /// before that and `Some` after. - have_destructor: Option>, - - /// The set of (`ItemId's of`) types that has array. - /// - /// Populated when we enter codegen by `compute_has_type_param_in_array`; always `None` - /// before that and `Some` after. - has_type_param_in_array: Option>, - - /// The set of (`ItemId's of`) types that has float. - /// - /// Populated when we enter codegen by `compute_has_float`; always `None` - /// before that and `Some` after. - has_float: Option>, -} - -/// A traversal of whitelisted items. -struct WhitelistedItemsTraversal<'ctx> { - ctx: &'ctx BindgenContext, - traversal: ItemTraversal< - 'ctx, - ItemSet, - Vec, - for<'a> fn(&'a BindgenContext, Edge) -> bool, - >, -} - -impl<'ctx> Iterator for WhitelistedItemsTraversal<'ctx> { - type Item = ItemId; - - fn next(&mut self) -> Option { - loop { - let id = self.traversal.next()?; - - if self.ctx.resolve_item(id).is_blacklisted(self.ctx) { - continue - } - - return Some(id); - } - } -} - -impl<'ctx> WhitelistedItemsTraversal<'ctx> { - /// Construct a new whitelisted items traversal. - pub fn new( - ctx: &'ctx BindgenContext, - roots: R, - predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool, - ) -> Self - where - R: IntoIterator, - { - WhitelistedItemsTraversal { - ctx, - traversal: ItemTraversal::new(ctx, roots, predicate), - } - } -} - -const HOST_TARGET: &'static str = - include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); - -/// Returns the effective target, and whether it was explicitly specified on the -/// clang flags. -fn find_effective_target(clang_args: &[String]) -> (String, bool) { - use std::env; - - for opt in clang_args { - if opt.starts_with("--target=") { - let mut split = opt.split('='); - split.next(); - return (split.next().unwrap().to_owned(), true); - } - } - - // If we're running from a build script, try to find the cargo target. - if let Ok(t) = env::var("TARGET") { - return (t, false) - } - - (HOST_TARGET.to_owned(), false) -} - -impl BindgenContext { - /// Construct the context for the given `options`. - pub(crate) fn new(options: BindgenOptions) -> Self { - use clang_sys; - - // TODO(emilio): Use the CXTargetInfo here when available. - // - // see: https://reviews.llvm.org/D32389 - let (effective_target, explicit_target) = - find_effective_target(&options.clang_args); - - let index = clang::Index::new(false, true); - - let parse_options = - clang_sys::CXTranslationUnit_DetailedPreprocessingRecord; - - let translation_unit = { - let clang_args = if explicit_target { - Cow::Borrowed(&options.clang_args) - } else { - let mut args = Vec::with_capacity(options.clang_args.len() + 1); - args.push(format!("--target={}", effective_target)); - args.extend_from_slice(&options.clang_args); - Cow::Owned(args) - }; - - clang::TranslationUnit::parse( - &index, - "", - &clang_args, - &options.input_unsaved_files, - parse_options, - ).expect("TranslationUnit::parse failed") - }; - - let target_info = clang::TargetInfo::new(&translation_unit); - - #[cfg(debug_assertions)] - { - if let Some(ref ti) = target_info { - if effective_target == HOST_TARGET { - assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>()); - } - } - } - - let root_module = Self::build_root_module(ItemId(0)); - let root_module_id = root_module.id().as_module_id_unchecked(); - - let mut me = BindgenContext { - items: Default::default(), - types: Default::default(), - type_params: Default::default(), - modules: Default::default(), - next_item_id: ItemId(1), - root_module: root_module_id, - current_module: root_module_id, - semantic_parents: Default::default(), - currently_parsed_types: vec![], - parsed_macros: Default::default(), - replacements: Default::default(), - collected_typerefs: false, - in_codegen: false, - index, - translation_unit, - target_info, - options, - generated_bindegen_complex: Cell::new(false), - whitelisted: None, - codegen_items: None, - used_template_parameters: None, - need_bitfield_allocation: Default::default(), - cannot_derive_debug: None, - cannot_derive_default: None, - cannot_derive_copy: None, - cannot_derive_copy_in_array: None, - cannot_derive_hash: None, - cannot_derive_partialeq_or_partialord: None, - sizedness: None, - have_vtable: None, - have_destructor: None, - has_type_param_in_array: None, - has_float: None, - }; - - me.add_item(root_module, None, None); - - me - } - - /// Creates a timer for the current bindgen phase. If time_phases is `true`, - /// the timer will print to stderr when it is dropped, otherwise it will do - /// nothing. - pub fn timer<'a>(&self, name: &'a str) -> Timer<'a> { - Timer::new(name).with_output(self.options.time_phases) - } - - /// Returns the pointer width to use for the target for the current - /// translation. - pub fn target_pointer_size(&self) -> usize { - if let Some(ref ti) = self.target_info { - return ti.pointer_width / 8; - } - mem::size_of::<*mut ()>() - } - - /// Get the stack of partially parsed types that we are in the middle of - /// parsing. - pub fn currently_parsed_types(&self) -> &[PartialType] { - &self.currently_parsed_types[..] - } - - /// Begin parsing the given partial type, and push it onto the - /// `currently_parsed_types` stack so that we won't infinite recurse if we - /// run into a reference to it while parsing it. - pub fn begin_parsing(&mut self, partial_ty: PartialType) { - self.currently_parsed_types.push(partial_ty); - } - - /// Finish parsing the current partial type, pop it off the - /// `currently_parsed_types` stack, and return it. - pub fn finish_parsing(&mut self) -> PartialType { - self.currently_parsed_types.pop().expect( - "should have been parsing a type, if we finished parsing a type", - ) - } - - /// Get the user-provided callbacks by reference, if any. - pub fn parse_callbacks(&self) -> Option<&ParseCallbacks> { - self.options().parse_callbacks.as_ref().map(|t| &**t) - } - - /// Define a new item. - /// - /// This inserts it into the internal items set, and its type into the - /// internal types set. - pub fn add_item( - &mut self, - item: Item, - declaration: Option, - location: Option, - ) { - debug!( - "BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}", - item, - declaration, - location - ); - debug_assert!( - declaration.is_some() || !item.kind().is_type() || - item.kind().expect_type().is_builtin_or_type_param() || - item.kind().expect_type().is_opaque(self, &item), - "Adding a type without declaration?" - ); - - let id = item.id(); - let is_type = item.kind().is_type(); - let is_unnamed = is_type && item.expect_type().name().is_none(); - let is_template_instantiation = is_type && - item.expect_type().is_template_instantiation(); - - if item.id() != self.root_module { - self.add_item_to_module(&item); - } - - if is_type && item.expect_type().is_comp() { - self.need_bitfield_allocation.push(id); - } - - let old_item = self.items.insert(id, item); - assert!( - old_item.is_none(), - "should not have already associated an item with the given id" - ); - - // Unnamed items can have an USR, but they can't be referenced from - // other sites explicitly and the USR can match if the unnamed items are - // nested, so don't bother tracking them. - if is_type && !is_template_instantiation && declaration.is_some() { - let mut declaration = declaration.unwrap(); - if !declaration.is_valid() { - if let Some(location) = location { - if location.is_template_like() { - declaration = location; - } - } - } - declaration = declaration.canonical(); - if !declaration.is_valid() { - // This could happen, for example, with types like `int*` or - // similar. - // - // Fortunately, we don't care about those types being - // duplicated, so we can just ignore them. - debug!( - "Invalid declaration {:?} found for type {:?}", - declaration, - self.items.get(&id).unwrap().kind().expect_type() - ); - return; - } - - let key = if is_unnamed { - TypeKey::Declaration(declaration) - } else if let Some(usr) = declaration.usr() { - TypeKey::USR(usr) - } else { - warn!( - "Valid declaration with no USR: {:?}, {:?}", - declaration, - location - ); - TypeKey::Declaration(declaration) - }; - - let old = self.types.insert(key, id.as_type_id_unchecked()); - debug_assert_eq!(old, None); - } - } - - /// Ensure that every item (other than the root module) is in a module's - /// children list. This is to make sure that every whitelisted item get's - /// codegen'd, even if its parent is not whitelisted. See issue #769 for - /// details. - fn add_item_to_module(&mut self, item: &Item) { - assert!(item.id() != self.root_module); - assert!(!self.items.contains_key(&item.id())); - - if let Some(parent) = self.items.get_mut(&item.parent_id()) { - if let Some(module) = parent.as_module_mut() { - debug!( - "add_item_to_module: adding {:?} as child of parent module {:?}", - item.id(), - item.parent_id() - ); - - module.children_mut().insert(item.id()); - return; - } - } - - debug!( - "add_item_to_module: adding {:?} as child of current module {:?}", - item.id(), - self.current_module - ); - - self.items - .get_mut(&self.current_module.into()) - .expect("Should always have an item for self.current_module") - .as_module_mut() - .expect("self.current_module should always be a module") - .children_mut() - .insert(item.id()); - } - - /// Add a new named template type parameter to this context's item set. - pub fn add_type_param(&mut self, item: Item, definition: clang::Cursor) { - debug!( - "BindgenContext::add_type_param: item = {:?}; definition = {:?}", - item, - definition - ); - - assert!( - item.expect_type().is_type_param(), - "Should directly be a named type, not a resolved reference or anything" - ); - assert_eq!( - definition.kind(), - clang_sys::CXCursor_TemplateTypeParameter - ); - - self.add_item_to_module(&item); - - let id = item.id(); - let old_item = self.items.insert(id, item); - assert!( - old_item.is_none(), - "should not have already associated an item with the given id" - ); - - let old_named_ty = self.type_params.insert(definition, id.as_type_id_unchecked()); - assert!( - old_named_ty.is_none(), - "should not have already associated a named type with this id" - ); - } - - /// Get the named type defined at the given cursor location, if we've - /// already added one. - pub fn get_type_param(&self, definition: &clang::Cursor) -> Option { - assert_eq!( - definition.kind(), - clang_sys::CXCursor_TemplateTypeParameter - ); - self.type_params.get(definition).cloned() - } - - // TODO: Move all this syntax crap to other part of the code. - - /// Mangles a name so it doesn't conflict with any keyword. - pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> { - if name.contains("@") || - name.contains("?") || - name.contains("$") || - match name { - "abstract" | - "alignof" | - "as" | - "become" | - "box" | - "break" | - "const" | - "continue" | - "crate" | - "do" | - "else" | - "enum" | - "extern" | - "false" | - "final" | - "fn" | - "for" | - "if" | - "impl" | - "in" | - "let" | - "loop" | - "macro" | - "match" | - "mod" | - "move" | - "mut" | - "offsetof" | - "override" | - "priv" | - "proc" | - "pub" | - "pure" | - "ref" | - "return" | - "Self" | - "self" | - "sizeof" | - "static" | - "struct" | - "super" | - "trait" | - "true" | - "type" | - "typeof" | - "unsafe" | - "unsized" | - "use" | - "virtual" | - "where" | - "while" | - "yield" | - "bool" | - "_" => true, - _ => false, - } - { - let mut s = name.to_owned(); - s = s.replace("@", "_"); - s = s.replace("?", "_"); - s = s.replace("$", "_"); - s.push_str("_"); - return Cow::Owned(s); - } - Cow::Borrowed(name) - } - - /// Returns a mangled name as a rust identifier. - pub fn rust_ident(&self, name: S) -> Term - where - S: AsRef - { - self.rust_ident_raw(self.rust_mangle(name.as_ref())) - } - - /// Returns a mangled name as a rust identifier. - pub fn rust_ident_raw(&self, name: T) -> Term - where - T: AsRef - { - Term::new(name.as_ref(), Span::call_site()) - } - - /// Iterate over all items that have been defined. - pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> { - self.items.iter() - } - - /// Have we collected all unresolved type references yet? - pub fn collected_typerefs(&self) -> bool { - self.collected_typerefs - } - - /// Gather all the unresolved type references. - fn collect_typerefs( - &mut self, - ) -> Vec<(ItemId, clang::Type, clang::Cursor, Option)> { - debug_assert!(!self.collected_typerefs); - self.collected_typerefs = true; - let mut typerefs = vec![]; - for (id, ref mut item) in &mut self.items { - let kind = item.kind(); - let ty = match kind.as_type() { - Some(ty) => ty, - None => continue, - }; - - match *ty.kind() { - TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => { - typerefs.push((*id, ty.clone(), loc, parent_id)); - } - _ => {} - }; - } - typerefs - } - - /// Collect all of our unresolved type references and resolve them. - fn resolve_typerefs(&mut self) { - let typerefs = self.collect_typerefs(); - - for (id, ty, loc, parent_id) in typerefs { - let _resolved = { - let resolved = Item::from_ty(&ty, loc, parent_id, self) - .unwrap_or_else(|_| { - warn!("Could not resolve type reference, falling back \ - to opaque blob"); - Item::new_opaque_type(self.next_item_id(), &ty, self) - }); - - let item = self.items.get_mut(&id).unwrap(); - *item.kind_mut().as_type_mut().unwrap().kind_mut() = - TypeKind::ResolvedTypeRef(resolved); - resolved - }; - - // Something in the STL is trolling me. I don't need this assertion - // right now, but worth investigating properly once this lands. - // - // debug_assert!(self.items.get(&resolved).is_some(), "How?"); - // - // if let Some(parent_id) = parent_id { - // assert_eq!(self.items[&resolved].parent_id(), parent_id); - // } - } - } - - /// Temporarily loan `Item` with the given `ItemId`. This provides means to - /// mutably borrow `Item` while having a reference to `BindgenContext`. - /// - /// `Item` with the given `ItemId` is removed from the context, given - /// closure is executed and then `Item` is placed back. - /// - /// # Panics - /// - /// Panics if attempt to resolve given `ItemId` inside the given - /// closure is made. - fn with_loaned_item(&mut self, id: ItemId, f: F) -> T - where - F: (FnOnce(&BindgenContext, &mut Item) -> T) - { - let mut item = self.items.remove(&id).unwrap(); - - let result = f(self, &mut item); - - let existing = self.items.insert(id, item); - assert!(existing.is_none()); - - result - } - - /// Compute the bitfield allocation units for all `TypeKind::Comp` items we - /// parsed. - fn compute_bitfield_units(&mut self) { - assert!(self.collected_typerefs()); - - let need_bitfield_allocation = - mem::replace(&mut self.need_bitfield_allocation, vec![]); - for id in need_bitfield_allocation { - self.with_loaned_item(id, |ctx, item| { - item.kind_mut() - .as_type_mut() - .unwrap() - .as_comp_mut() - .unwrap() - .compute_bitfield_units(ctx); - }); - } - } - - /// Assign a new generated name for each anonymous field. - fn deanonymize_fields(&mut self) { - let _t = self.timer("deanonymize_fields"); - - let comp_item_ids: Vec = self.items - .iter() - .filter_map(|(id, item)| { - if item.kind().as_type()?.is_comp() { - return Some(id); - } - None - }) - .cloned() - .collect(); - - for id in comp_item_ids { - self.with_loaned_item(id, |ctx, item| { - item.kind_mut() - .as_type_mut() - .unwrap() - .as_comp_mut() - .unwrap() - .deanonymize_fields(ctx); - }); - } - } - - /// Iterate over all items and replace any item that has been named in a - /// `replaces="SomeType"` annotation with the replacement type. - fn process_replacements(&mut self) { - let _t = self.timer("process_replacements"); - if self.replacements.is_empty() { - debug!("No replacements to process"); - return; - } - - // FIXME: This is linear, but the replaces="xxx" annotation was already - // there, and for better or worse it's useful, sigh... - // - // We leverage the ResolvedTypeRef thing, though, which is cool :P. - - let mut replacements = vec![]; - - for (id, item) in self.items.iter() { - if item.annotations().use_instead_of().is_some() { - continue; - } - - // Calls to `canonical_name` are expensive, so eagerly filter out - // items that cannot be replaced. - let ty = match item.kind().as_type() { - Some(ty) => ty, - None => continue, - }; - - match *ty.kind() { - TypeKind::Comp(..) | - TypeKind::TemplateAlias(..) | - TypeKind::Enum(..) | - TypeKind::Alias(..) => {} - _ => continue, - } - - let path = item.canonical_path(self); - let replacement = self.replacements.get(&path[1..]); - - if let Some(replacement) = replacement { - if replacement != id { - // We set this just after parsing the annotation. It's - // very unlikely, but this can happen. - if self.items.get(replacement).is_some() { - replacements.push((id.expect_type_id(self), replacement.expect_type_id(self))); - } - } - } - } - - for (id, replacement_id) in replacements { - debug!("Replacing {:?} with {:?}", id, replacement_id); - - let new_parent = { - let item = self.items.get_mut(&id.into()).unwrap(); - *item.kind_mut().as_type_mut().unwrap().kind_mut() = - TypeKind::ResolvedTypeRef(replacement_id); - item.parent_id() - }; - - // Relocate the replacement item from where it was declared, to - // where the thing it is replacing was declared. - // - // First, we'll make sure that its parent id is correct. - - let old_parent = self.resolve_item(replacement_id).parent_id(); - if new_parent == old_parent { - // Same parent and therefore also same containing - // module. Nothing to do here. - continue; - } - - self.items - .get_mut(&replacement_id.into()) - .unwrap() - .set_parent_for_replacement(new_parent); - - // Second, make sure that it is in the correct module's children - // set. - - let old_module = { - let immut_self = &*self; - old_parent - .ancestors(immut_self) - .chain(Some(immut_self.root_module.into())) - .find(|id| { - let item = immut_self.resolve_item(*id); - item.as_module().map_or(false, |m| { - m.children().contains(&replacement_id.into()) - }) - }) - }; - let old_module = old_module.expect( - "Every replacement item should be in a module", - ); - - let new_module = { - let immut_self = &*self; - new_parent.ancestors(immut_self).find(|id| { - immut_self.resolve_item(*id).is_module() - }) - }; - let new_module = new_module.unwrap_or(self.root_module.into()); - - if new_module == old_module { - // Already in the correct module. - continue; - } - - self.items - .get_mut(&old_module) - .unwrap() - .as_module_mut() - .unwrap() - .children_mut() - .remove(&replacement_id.into()); - - self.items - .get_mut(&new_module) - .unwrap() - .as_module_mut() - .unwrap() - .children_mut() - .insert(replacement_id.into()); - } - } - - /// Enter the code generation phase, invoke the given callback `cb`, and - /// leave the code generation phase. - pub(crate) fn gen(mut self, cb: F) -> (Out, BindgenOptions) - where - F: FnOnce(&Self) -> Out, - { - self.in_codegen = true; - - self.resolve_typerefs(); - self.compute_bitfield_units(); - self.process_replacements(); - - self.deanonymize_fields(); - - self.assert_no_dangling_references(); - - // Compute the whitelisted set after processing replacements and - // resolving type refs, as those are the final mutations of the IR - // graph, and their completion means that the IR graph is now frozen. - self.compute_whitelisted_and_codegen_items(); - - // Make sure to do this after processing replacements, since that messes - // with the parentage and module children, and we want to assert that it - // messes with them correctly. - self.assert_every_item_in_a_module(); - - self.compute_has_vtable(); - self.compute_sizedness(); - self.compute_has_destructor(); - self.find_used_template_parameters(); - self.compute_cannot_derive_debug(); - self.compute_cannot_derive_default(); - self.compute_cannot_derive_copy(); - self.compute_has_type_param_in_array(); - self.compute_has_float(); - self.compute_cannot_derive_hash(); - self.compute_cannot_derive_partialord_partialeq_or_eq(); - - let ret = cb(&self); - (ret, self.options) - } - - /// When the `testing_only_extra_assertions` feature is enabled, this - /// function walks the IR graph and asserts that we do not have any edges - /// referencing an ItemId for which we do not have an associated IR item. - fn assert_no_dangling_references(&self) { - if cfg!(feature = "testing_only_extra_assertions") { - for _ in self.assert_no_dangling_item_traversal() { - // The iterator's next method does the asserting for us. - } - } - } - - fn assert_no_dangling_item_traversal( - &self, - ) -> traversal::AssertNoDanglingItemsTraversal { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - - let roots = self.items().map(|(&id, _)| id); - traversal::AssertNoDanglingItemsTraversal::new( - self, - roots, - traversal::all_edges, - ) - } - - /// When the `testing_only_extra_assertions` feature is enabled, walk over - /// every item and ensure that it is in the children set of one of its - /// module ancestors. - fn assert_every_item_in_a_module(&self) { - if cfg!(feature = "testing_only_extra_assertions") { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - - for (&id, _item) in self.items() { - if id == self.root_module { - continue; - } - - assert!( - { - let id = id.into_resolver() - .through_type_refs() - .through_type_aliases() - .resolve(self) - .id(); - id.ancestors(self).chain(Some(self.root_module.into())).any( - |ancestor| { - debug!( - "Checking if {:?} is a child of {:?}", - id, - ancestor - ); - self.resolve_item(ancestor).as_module().map_or( - false, - |m| { - m.children().contains(&id) - }, - ) - }, - ) - }, - "{:?} should be in some ancestor module's children set", - id - ); - } - } - } - - /// Compute for every type whether it is sized or not, and whether it is - /// sized or not as a base class. - fn compute_sizedness(&mut self) { - let _t = self.timer("compute_sizedness"); - assert!(self.sizedness.is_none()); - self.sizedness = Some(analyze::(self)); - } - - /// Look up whether the type with the given id is sized or not. - pub fn lookup_sizedness(&self, id: TypeId) -> SizednessResult { - assert!( - self.in_codegen_phase(), - "We only compute sizedness after we've entered codegen" - ); - - self.sizedness - .as_ref() - .unwrap() - .get(&id) - .cloned() - .unwrap_or(SizednessResult::ZeroSized) - } - - /// Compute whether the type has vtable. - fn compute_has_vtable(&mut self) { - let _t = self.timer("compute_has_vtable"); - assert!(self.have_vtable.is_none()); - self.have_vtable = Some(analyze::(self)); - } - - /// Look up whether the item with `id` has vtable or not. - pub fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult { - assert!( - self.in_codegen_phase(), - "We only compute vtables when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` has a - // vtable or not. - self.have_vtable - .as_ref() - .unwrap() - .get(&id.into()) - .cloned() - .unwrap_or(HasVtableResult::No) - } - - /// Compute whether the type has a destructor. - fn compute_has_destructor(&mut self) { - let _t = self.timer("compute_has_destructor"); - assert!(self.have_destructor.is_none()); - self.have_destructor = Some(analyze::(self)); - } - - /// Look up whether the item with `id` has a destructor. - pub fn lookup_has_destructor(&self, id: TypeId) -> bool { - assert!( - self.in_codegen_phase(), - "We only compute destructors when we enter codegen" - ); - - self.have_destructor.as_ref().unwrap().contains(&id.into()) - } - - fn find_used_template_parameters(&mut self) { - let _t = self.timer("find_used_template_parameters"); - if self.options.whitelist_recursively { - let used_params = analyze::(self); - self.used_template_parameters = Some(used_params); - } else { - // If you aren't recursively whitelisting, then we can't really make - // any sense of template parameter usage, and you're on your own. - let mut used_params = HashMap::new(); - for &id in self.whitelisted_items() { - used_params.entry(id).or_insert( - id.self_template_params(self).map_or( - Default::default(), - |params| params.into_iter().map(|p| p.into()).collect(), - ), - ); - } - self.used_template_parameters = Some(used_params); - } - } - - /// Return `true` if `item` uses the given `template_param`, `false` - /// otherwise. - /// - /// This method may only be called during the codegen phase, because the - /// template usage information is only computed as we enter the codegen - /// phase. - /// - /// If the item is blacklisted, then we say that it always uses the template - /// parameter. This is a little subtle. The template parameter usage - /// analysis only considers whitelisted items, and if any blacklisted item - /// shows up in the generated bindings, it is the user's responsibility to - /// manually provide a definition for them. To give them the most - /// flexibility when doing that, we assume that they use every template - /// parameter and always pass template arguments through in instantiations. - pub fn uses_template_parameter( - &self, - item: ItemId, - template_param: TypeId, - ) -> bool { - assert!( - self.in_codegen_phase(), - "We only compute template parameter usage as we enter codegen" - ); - - if self.resolve_item(item).is_blacklisted(self) { - return true; - } - - let template_param = template_param - .into_resolver() - .through_type_refs() - .through_type_aliases() - .resolve(self) - .id(); - - self.used_template_parameters - .as_ref() - .expect("should have found template parameter usage if we're in codegen") - .get(&item) - .map_or(false, |items_used_params| items_used_params.contains(&template_param)) - } - - /// Return `true` if `item` uses any unbound, generic template parameters, - /// `false` otherwise. - /// - /// Has the same restrictions that `uses_template_parameter` has. - pub fn uses_any_template_parameters(&self, item: ItemId) -> bool { - assert!( - self.in_codegen_phase(), - "We only compute template parameter usage as we enter codegen" - ); - - self.used_template_parameters - .as_ref() - .expect( - "should have template parameter usage info in codegen phase", - ) - .get(&item) - .map_or(false, |used| !used.is_empty()) - } - - // This deserves a comment. Builtin types don't get a valid declaration, so - // we can't add it to the cursor->type map. - // - // That being said, they're not generated anyway, and are few, so the - // duplication and special-casing is fine. - // - // If at some point we care about the memory here, probably a map TypeKind - // -> builtin type ItemId would be the best to improve that. - fn add_builtin_item(&mut self, item: Item) { - debug!("add_builtin_item: item = {:?}", item); - debug_assert!(item.kind().is_type()); - self.add_item_to_module(&item); - let id = item.id(); - let old_item = self.items.insert(id, item); - assert!(old_item.is_none(), "Inserted type twice?"); - } - - fn build_root_module(id: ItemId) -> Item { - let module = Module::new(Some("root".into()), ModuleKind::Normal); - Item::new(id, None, None, id, ItemKind::Module(module)) - } - - /// Get the root module. - pub fn root_module(&self) -> ModuleId { - self.root_module - } - - /// Resolve a type with the given id. - /// - /// Panics if there is no item for the given `TypeId` or if the resolved - /// item is not a `Type`. - pub fn resolve_type(&self, type_id: TypeId) -> &Type { - self.resolve_item(type_id).kind().expect_type() - } - - /// Resolve a function with the given id. - /// - /// Panics if there is no item for the given `FunctionId` or if the resolved - /// item is not a `Function`. - pub fn resolve_func(&self, func_id: FunctionId) -> &Function { - self.resolve_item(func_id).kind().expect_function() - } - - /// Resolve the given `ItemId` as a type, or `None` if there is no item with - /// the given id. - /// - /// Panics if the id resolves to an item that is not a type. - pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> { - self.items.get(&type_id.into()).map(|t| t.kind().expect_type()) - } - - /// Resolve the given `ItemId` into an `Item`, or `None` if no such item - /// exists. - pub fn resolve_item_fallible>(&self, id: Id) -> Option<&Item> { - self.items.get(&id.into()) - } - - /// Resolve the given `ItemId` into an `Item`. - /// - /// Panics if the given id does not resolve to any item. - pub fn resolve_item>(&self, item_id: Id) -> &Item { - let item_id = item_id.into(); - match self.items.get(&item_id) { - Some(item) => item, - None => panic!("Not an item: {:?}", item_id), - } - } - - /// Get the current module. - pub fn current_module(&self) -> ModuleId { - self.current_module - } - - /// Add a semantic parent for a given type definition. - /// - /// We do this from the type declaration, in order to be able to find the - /// correct type definition afterwards. - /// - /// TODO(emilio): We could consider doing this only when - /// declaration.lexical_parent() != definition.lexical_parent(), but it's - /// not sure it's worth it. - pub fn add_semantic_parent( - &mut self, - definition: clang::Cursor, - parent_id: ItemId, - ) { - self.semantic_parents.insert(definition, parent_id); - } - - /// Returns a known semantic parent for a given definition. - pub fn known_semantic_parent( - &self, - definition: clang::Cursor - ) -> Option { - self.semantic_parents.get(&definition).cloned() - } - - - /// Given a cursor pointing to the location of a template instantiation, - /// return a tuple of the form `(declaration_cursor, declaration_id, - /// num_expected_template_args)`. - /// - /// Note that `declaration_id` is not guaranteed to be in the context's item - /// set! It is possible that it is a partial type that we are still in the - /// middle of parsign. - fn get_declaration_info_for_template_instantiation( - &self, - instantiation: &Cursor, - ) -> Option<(Cursor, ItemId, usize)> { - instantiation - .cur_type() - .canonical_declaration(Some(instantiation)) - .and_then(|canon_decl| { - self.get_resolved_type(&canon_decl).and_then( - |template_decl_id| { - template_decl_id.num_self_template_params(self).map( - |num_params| { - ( - *canon_decl.cursor(), - template_decl_id.into(), - num_params, - ) - }, - ) - }, - ) - }) - .or_else(|| { - // If we haven't already parsed the declaration of - // the template being instantiated, then it *must* - // be on the stack of types we are currently - // parsing. If it wasn't then clang would have - // already errored out before we started - // constructing our IR because you can't instantiate - // a template until it is fully defined. - instantiation - .referenced() - .and_then(|referenced| { - self.currently_parsed_types() - .iter() - .find(|partial_ty| *partial_ty.decl() == referenced) - .cloned() - }) - .and_then(|template_decl| { - template_decl.num_self_template_params(self).map( - |num_template_params| { - ( - *template_decl.decl(), - template_decl.id(), - num_template_params, - ) - }, - ) - }) - }) - } - - /// Parse a template instantiation, eg `Foo`. - /// - /// This is surprisingly difficult to do with libclang, due to the fact that - /// it doesn't provide explicit template argument information, except for - /// function template declarations(!?!??!). - /// - /// The only way to do this is manually inspecting the AST and looking for - /// TypeRefs and TemplateRefs inside. This, unfortunately, doesn't work for - /// more complex cases, see the comment on the assertion below. - /// - /// To add insult to injury, the AST itself has structure that doesn't make - /// sense. Sometimes `Foo>` has an AST with nesting like you might - /// expect: `(Foo (Bar (int)))`. Other times, the AST we get is completely - /// flat: `(Foo Bar int)`. - /// - /// To see an example of what this method handles: - /// - /// ```c++ - /// template - /// class Incomplete { - /// T p; - /// }; - /// - /// template - /// class Foo { - /// Incomplete bar; - /// }; - /// ``` - /// - /// Finally, template instantiations are always children of the current - /// module. They use their template's definition for their name, so the - /// parent is only useful for ensuring that their layout tests get - /// codegen'd. - fn instantiate_template( - &mut self, - with_id: ItemId, - template: TypeId, - ty: &clang::Type, - location: clang::Cursor, - ) -> Option { - use clang_sys; - - let num_expected_args = match self.resolve_type(template) - .num_self_template_params(self) { - Some(n) => n, - None => { - warn!( - "Tried to instantiate a template for which we could not \ - determine any template parameters" - ); - return None; - } - }; - - let mut args = vec![]; - let mut found_const_arg = false; - let mut children = location.collect_children(); - - if children.iter().all(|c| !c.has_children()) { - // This is insanity... If clang isn't giving us a properly nested - // AST for which template arguments belong to which template we are - // instantiating, we'll need to construct it ourselves. However, - // there is an extra `NamespaceRef, NamespaceRef, ..., TemplateRef` - // representing a reference to the outermost template declaration - // that we need to filter out of the children. We need to do this - // filtering because we already know which template declaration is - // being specialized via the `location`'s type, and if we do not - // filter it out, we'll add an extra layer of template instantiation - // on accident. - let idx = children.iter().position(|c| { - c.kind() == clang_sys::CXCursor_TemplateRef - }); - if let Some(idx) = idx { - if children.iter().take(idx).all(|c| { - c.kind() == clang_sys::CXCursor_NamespaceRef - }) - { - children = children.into_iter().skip(idx + 1).collect(); - } - } - } - - for child in children.iter().rev() { - match child.kind() { - clang_sys::CXCursor_TypeRef | - clang_sys::CXCursor_TypedefDecl | - clang_sys::CXCursor_TypeAliasDecl => { - // The `with_id` id will potentially end up unused if we give up - // on this type (for example, because it has const value - // template args), so if we pass `with_id` as the parent, it is - // potentially a dangling reference. Instead, use the canonical - // template declaration as the parent. It is already parsed and - // has a known-resolvable `ItemId`. - let ty = Item::from_ty_or_ref( - child.cur_type(), - *child, - Some(template.into()), - self, - ); - args.push(ty); - } - clang_sys::CXCursor_TemplateRef => { - let (template_decl_cursor, template_decl_id, num_expected_template_args) = - self.get_declaration_info_for_template_instantiation(child)?; - - if num_expected_template_args == 0 || - child.has_at_least_num_children( - num_expected_template_args, - ) - { - // Do a happy little parse. See comment in the TypeRef - // match arm about parent IDs. - let ty = Item::from_ty_or_ref( - child.cur_type(), - *child, - Some(template.into()), - self, - ); - args.push(ty); - } else { - // This is the case mentioned in the doc comment where - // clang gives us a flattened AST and we have to - // reconstruct which template arguments go to which - // instantiation :( - let args_len = args.len(); - if args_len < num_expected_template_args { - warn!( - "Found a template instantiation without \ - enough template arguments" - ); - return None; - } - - let mut sub_args: Vec<_> = args - .drain(args_len - num_expected_template_args..) - .collect(); - sub_args.reverse(); - - let sub_name = Some(template_decl_cursor.spelling()); - let sub_inst = TemplateInstantiation::new( - // This isn't guaranteed to be a type that we've - // already finished parsing yet. - template_decl_id.as_type_id_unchecked(), - sub_args, - ); - let sub_kind = - TypeKind::TemplateInstantiation(sub_inst); - let sub_ty = Type::new( - sub_name, - template_decl_cursor - .cur_type() - .fallible_layout() - .ok(), - sub_kind, - false, - ); - let sub_id = self.next_item_id(); - let sub_item = Item::new( - sub_id, - None, - None, - self.current_module.into(), - ItemKind::Type(sub_ty), - ); - - // Bypass all the validations in add_item explicitly. - debug!( - "instantiate_template: inserting nested \ - instantiation item: {:?}", - sub_item - ); - self.add_item_to_module(&sub_item); - debug_assert!(sub_id == sub_item.id()); - self.items.insert(sub_id, sub_item); - args.push(sub_id.as_type_id_unchecked()); - } - } - _ => { - warn!( - "Found template arg cursor we can't handle: {:?}", - child - ); - found_const_arg = true; - } - } - } - - if found_const_arg { - // This is a dependently typed template instantiation. That is, an - // instantiation of a template with one or more const values as - // template arguments, rather than only types as template - // arguments. For example, `Foo` versus `Bar`. - // We can't handle these instantiations, so just punt in this - // situation... - warn!( - "Found template instantiated with a const value; \ - bindgen can't handle this kind of template instantiation!" - ); - return None; - } - - if args.len() != num_expected_args { - warn!( - "Found a template with an unexpected number of template \ - arguments" - ); - return None; - } - - args.reverse(); - let type_kind = TypeKind::TemplateInstantiation( - TemplateInstantiation::new(template, args), - ); - let name = ty.spelling(); - let name = if name.is_empty() { None } else { Some(name) }; - let ty = Type::new( - name, - ty.fallible_layout().ok(), - type_kind, - ty.is_const(), - ); - let item = Item::new( - with_id, - None, - None, - self.current_module.into(), - ItemKind::Type(ty), - ); - - // Bypass all the validations in add_item explicitly. - debug!("instantiate_template: inserting item: {:?}", item); - self.add_item_to_module(&item); - debug_assert!(with_id == item.id()); - self.items.insert(with_id, item); - Some(with_id.as_type_id_unchecked()) - } - - /// If we have already resolved the type for the given type declaration, - /// return its `ItemId`. Otherwise, return `None`. - pub fn get_resolved_type( - &self, - decl: &clang::CanonicalTypeDeclaration, - ) -> Option { - self.types - .get(&TypeKey::Declaration(*decl.cursor())) - .or_else(|| { - decl.cursor().usr().and_then( - |usr| self.types.get(&TypeKey::USR(usr)), - ) - }) - .cloned() - } - - /// Looks up for an already resolved type, either because it's builtin, or - /// because we already have it in the map. - pub fn builtin_or_resolved_ty( - &mut self, - with_id: ItemId, - parent_id: Option, - ty: &clang::Type, - location: Option, - ) -> Option { - use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef}; - debug!( - "builtin_or_resolved_ty: {:?}, {:?}, {:?}", - ty, - location, - parent_id - ); - - if let Some(decl) = ty.canonical_declaration(location.as_ref()) { - if let Some(id) = self.get_resolved_type(&decl) { - debug!( - "Already resolved ty {:?}, {:?}, {:?} {:?}", - id, - decl, - ty, - location - ); - // If the declaration already exists, then either: - // - // * the declaration is a template declaration of some sort, - // and we are looking at an instantiation or specialization - // of it, or - // * we have already parsed and resolved this type, and - // there's nothing left to do. - if decl.cursor().is_template_like() && - *ty != decl.cursor().cur_type() && - location.is_some() - { - let location = location.unwrap(); - - // For specialized type aliases, there's no way to get the - // template parameters as of this writing (for a struct - // specialization we wouldn't be in this branch anyway). - // - // Explicitly return `None` if there aren't any - // unspecialized parameters (contains any `TypeRef`) so we - // resolve the canonical type if there is one and it's - // exposed. - // - // This is _tricky_, I know :( - if decl.cursor().kind() == CXCursor_TypeAliasTemplateDecl && - !location.contains_cursor(CXCursor_TypeRef) && - ty.canonical_type().is_valid_and_exposed() - { - return None; - } - - return self.instantiate_template(with_id, id, ty, location) - .or_else(|| Some(id)); - } - - return Some(self.build_ty_wrapper(with_id, id, parent_id, ty)); - } - } - - debug!("Not resolved, maybe builtin?"); - self.build_builtin_ty(ty) - } - - /// Make a new item that is a resolved type reference to the `wrapped_id`. - /// - /// This is unfortunately a lot of bloat, but is needed to properly track - /// constness et. al. - /// - /// We should probably make the constness tracking separate, so it doesn't - /// bloat that much, but hey, we already bloat the heck out of builtin - /// types. - pub fn build_ty_wrapper( - &mut self, - with_id: ItemId, - wrapped_id: TypeId, - parent_id: Option, - ty: &clang::Type, - ) -> TypeId { - let spelling = ty.spelling(); - let is_const = ty.is_const(); - let layout = ty.fallible_layout().ok(); - let type_kind = TypeKind::ResolvedTypeRef(wrapped_id); - let ty = Type::new(Some(spelling), layout, type_kind, is_const); - let item = Item::new( - with_id, - None, - None, - parent_id.unwrap_or(self.current_module.into()), - ItemKind::Type(ty), - ); - self.add_builtin_item(item); - with_id.as_type_id_unchecked() - } - - /// Returns the next item id to be used for an item. - pub fn next_item_id(&mut self) -> ItemId { - let ret = self.next_item_id; - self.next_item_id = ItemId(self.next_item_id.0 + 1); - ret - } - - fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option { - use clang_sys::*; - let type_kind = match ty.kind() { - CXType_NullPtr => TypeKind::NullPtr, - CXType_Void => TypeKind::Void, - CXType_Bool => TypeKind::Int(IntKind::Bool), - CXType_Int => TypeKind::Int(IntKind::Int), - CXType_UInt => TypeKind::Int(IntKind::UInt), - CXType_Char_S => TypeKind::Int(IntKind::Char { - is_signed: true, - }), - CXType_Char_U => TypeKind::Int(IntKind::Char { - is_signed: false, - }), - CXType_SChar => TypeKind::Int(IntKind::SChar), - CXType_UChar => TypeKind::Int(IntKind::UChar), - CXType_Short => TypeKind::Int(IntKind::Short), - CXType_UShort => TypeKind::Int(IntKind::UShort), - CXType_WChar | CXType_Char16 => TypeKind::Int(IntKind::U16), - CXType_Char32 => TypeKind::Int(IntKind::U32), - CXType_Long => TypeKind::Int(IntKind::Long), - CXType_ULong => TypeKind::Int(IntKind::ULong), - CXType_LongLong => TypeKind::Int(IntKind::LongLong), - CXType_ULongLong => TypeKind::Int(IntKind::ULongLong), - CXType_Int128 => TypeKind::Int(IntKind::I128), - CXType_UInt128 => TypeKind::Int(IntKind::U128), - CXType_Float => TypeKind::Float(FloatKind::Float), - CXType_Double => TypeKind::Float(FloatKind::Double), - CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble), - CXType_Float128 => TypeKind::Float(FloatKind::Float128), - CXType_Complex => { - let float_type = - ty.elem_type().expect("Not able to resolve complex type?"); - let float_kind = match float_type.kind() { - CXType_Float => FloatKind::Float, - CXType_Double => FloatKind::Double, - CXType_LongDouble => FloatKind::LongDouble, - CXType_Float128 => FloatKind::Float128, - _ => { - panic!( - "Non floating-type complex? {:?}, {:?}", - ty, - float_type, - ) - }, - }; - TypeKind::Complex(float_kind) - } - _ => return None, - }; - - let spelling = ty.spelling(); - let is_const = ty.is_const(); - let layout = ty.fallible_layout().ok(); - let ty = Type::new(Some(spelling), layout, type_kind, is_const); - let id = self.next_item_id(); - let item = - Item::new(id, None, None, self.root_module.into(), ItemKind::Type(ty)); - self.add_builtin_item(item); - Some(id.as_type_id_unchecked()) - } - - /// Get the current Clang translation unit that is being processed. - pub fn translation_unit(&self) -> &clang::TranslationUnit { - &self.translation_unit - } - - /// Have we parsed the macro named `macro_name` already? - pub fn parsed_macro(&self, macro_name: &[u8]) -> bool { - self.parsed_macros.contains_key(macro_name) - } - - /// Get the currently parsed macros. - pub fn parsed_macros(&self) -> &HashMap, cexpr::expr::EvalResult> { - debug_assert!(!self.in_codegen_phase()); - &self.parsed_macros - } - - /// Mark the macro named `macro_name` as parsed. - pub fn note_parsed_macro( - &mut self, - id: Vec, - value: cexpr::expr::EvalResult, - ) { - self.parsed_macros.insert(id, value); - } - - /// Are we in the codegen phase? - pub fn in_codegen_phase(&self) -> bool { - self.in_codegen - } - - /// Mark the type with the given `name` as replaced by the type with id - /// `potential_ty`. - /// - /// Replacement types are declared using the `replaces="xxx"` annotation, - /// and implies that the original type is hidden. - pub fn replace(&mut self, name: &[String], potential_ty: ItemId) { - match self.replacements.entry(name.into()) { - hash_map::Entry::Vacant(entry) => { - debug!( - "Defining replacement for {:?} as {:?}", - name, - potential_ty - ); - entry.insert(potential_ty); - } - hash_map::Entry::Occupied(occupied) => { - warn!( - "Replacement for {:?} already defined as {:?}; \ - ignoring duplicate replacement definition as {:?}", - name, - occupied.get(), - potential_ty - ); - } - } - } - - /// Is the item with the given `name` blacklisted? Or is the item with the given - /// `name` and `id` replaced by another type, and effectively blacklisted? - pub fn blacklisted_by_name>(&self, path: &[String], id: Id) -> bool { - let id = id.into(); - debug_assert!( - self.in_codegen_phase(), - "You're not supposed to call this yet" - ); - self.options.blacklisted_types.matches(&path[1..].join("::")) || - self.is_replaced_type(path, id) - } - - /// Has the item with the given `name` and `id` been replaced by another - /// type? - fn is_replaced_type>(&self, path: &[String], id: Id) -> bool { - let id = id.into(); - match self.replacements.get(path) { - Some(replaced_by) if *replaced_by != id => true, - _ => false, - } - } - - /// Is the type with the given `name` marked as opaque? - pub fn opaque_by_name(&self, path: &[String]) -> bool { - debug_assert!( - self.in_codegen_phase(), - "You're not supposed to call this yet" - ); - self.options.opaque_types.matches(&path[1..].join("::")) - } - - /// Get the options used to configure this bindgen context. - pub(crate) fn options(&self) -> &BindgenOptions { - &self.options - } - - /// Tokenizes a namespace cursor in order to get the name and kind of the - /// namespace. - fn tokenize_namespace( - &self, - cursor: &clang::Cursor, - ) -> (Option, ModuleKind) { - assert_eq!( - cursor.kind(), - ::clang_sys::CXCursor_Namespace, - "Be a nice person" - ); - let tokens = match cursor.tokens() { - Some(tokens) => tokens, - None => return (None, ModuleKind::Normal), - }; - - let mut iter = tokens.iter(); - let mut kind = ModuleKind::Normal; - let mut found_namespace_keyword = false; - let mut module_name = None; - - while let Some(token) = iter.next() { - match &*token.spelling { - "inline" => { - assert!(!found_namespace_keyword); - assert!(kind != ModuleKind::Inline); - kind = ModuleKind::Inline; - } - // The double colon allows us to handle nested namespaces like - // namespace foo::bar { } - // - // libclang still gives us two namespace cursors, which is cool, - // but the tokenization of the second begins with the double - // colon. That's ok, so we only need to handle the weird - // tokenization here. - // - // Fortunately enough, inline nested namespace specifiers aren't - // a thing, and are invalid C++ :) - "namespace" | "::" => { - found_namespace_keyword = true; - } - "{" => { - assert!(found_namespace_keyword); - break; - } - name if found_namespace_keyword => { - module_name = Some(name.to_owned()); - break; - } - _ => { - panic!( - "Unknown token while processing namespace: {:?}", - token - ); - } - } - } - - (module_name, kind) - } - - /// Given a CXCursor_Namespace cursor, return the item id of the - /// corresponding module, or create one on the fly. - pub fn module(&mut self, cursor: clang::Cursor) -> ModuleId { - use clang_sys::*; - assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person"); - let cursor = cursor.canonical(); - if let Some(id) = self.modules.get(&cursor) { - return *id; - } - - let (module_name, kind) = self.tokenize_namespace(&cursor); - - let module_id = self.next_item_id(); - let module = Module::new(module_name, kind); - let module = Item::new( - module_id, - None, - None, - self.current_module.into(), - ItemKind::Module(module), - ); - - let module_id = module.id().as_module_id_unchecked(); - self.modules.insert(cursor, module_id); - - self.add_item(module, None, None); - - module_id - } - - /// Start traversing the module with the given `module_id`, invoke the - /// callback `cb`, and then return to traversing the original module. - pub fn with_module(&mut self, module_id: ModuleId, cb: F) - where - F: FnOnce(&mut Self), - { - debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat"); - - let previous_id = self.current_module; - self.current_module = module_id; - - cb(self); - - self.current_module = previous_id; - } - - /// Iterate over all (explicitly or transitively) whitelisted items. - /// - /// If no items are explicitly whitelisted, then all items are considered - /// whitelisted. - pub fn whitelisted_items(&self) -> &ItemSet { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - - self.whitelisted.as_ref().unwrap() - } - - /// Get a reference to the set of items we should generate. - pub fn codegen_items(&self) -> &ItemSet { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - self.codegen_items.as_ref().unwrap() - } - - /// Compute the whitelisted items set and populate `self.whitelisted`. - fn compute_whitelisted_and_codegen_items(&mut self) { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - assert!(self.whitelisted.is_none()); - let _t = self.timer("compute_whitelisted_and_codegen_items"); - - let roots = { - let mut roots = self.items() - // Only consider roots that are enabled for codegen. - .filter(|&(_, item)| item.is_enabled_for_codegen(self)) - .filter(|&(_, item)| { - // If nothing is explicitly whitelisted, then everything is fair - // game. - if self.options().whitelisted_types.is_empty() && - self.options().whitelisted_functions.is_empty() && - self.options().whitelisted_vars.is_empty() { - return true; - } - - // If this is a type that explicitly replaces another, we assume - // you know what you're doing. - if item.annotations().use_instead_of().is_some() { - return true; - } - - let name = item.canonical_path(self)[1..].join("::"); - debug!("whitelisted_items: testing {:?}", name); - match *item.kind() { - ItemKind::Module(..) => true, - ItemKind::Function(_) => { - self.options().whitelisted_functions.matches(&name) - } - ItemKind::Var(_) => { - self.options().whitelisted_vars.matches(&name) - } - ItemKind::Type(ref ty) => { - if self.options().whitelisted_types.matches(&name) { - return true; - } - - let parent = self.resolve_item(item.parent_id()); - if parent.is_module() { - let mut prefix_path = parent.canonical_path(self); - - // Unnamed top-level enums are special and we - // whitelist them via the `whitelisted_vars` filter, - // since they're effectively top-level constants, - // and there's no way for them to be referenced - // consistently. - if let TypeKind::Enum(ref enum_) = *ty.kind() { - if ty.name().is_none() && - enum_.variants().iter().any(|variant| { - prefix_path.push(variant.name().into()); - let name = prefix_path[1..].join("::"); - prefix_path.pop().unwrap(); - self.options() - .whitelisted_vars - .matches(&name) - }) { - return true; - } - } - } - - false - } - } - }) - .map(|(&id, _)| id) - .collect::>(); - - // The reversal preserves the expected ordering of traversal, - // resulting in more stable-ish bindgen-generated names for - // anonymous types (like unions). - roots.reverse(); - roots - }; - - let whitelisted_items_predicate = - if self.options().whitelist_recursively { - traversal::all_edges - } else { - // Only follow InnerType edges from the whitelisted roots. - // Such inner types (e.g. anonymous structs/unions) are - // always emitted by codegen, and they need to be whitelisted - // to make sure they are processed by e.g. the derive analysis. - traversal::only_inner_type_edges - }; - - let whitelisted = WhitelistedItemsTraversal::new( - self, - roots.clone(), - whitelisted_items_predicate, - ).collect::(); - - let codegen_items = if self.options().whitelist_recursively { - WhitelistedItemsTraversal::new( - self, - roots.clone(), - traversal::codegen_edges, - ).collect::() - } else { - whitelisted.clone() - }; - - self.whitelisted = Some(whitelisted); - self.codegen_items = Some(codegen_items); - } - - /// Convenient method for getting the prefix to use for most traits in - /// codegen depending on the `use_core` option. - pub fn trait_prefix(&self) -> Term { - if self.options().use_core { - self.rust_ident_raw("core") - } else { - self.rust_ident_raw("std") - } - } - - /// Call if a binden complex is generated - pub fn generated_bindegen_complex(&self) { - self.generated_bindegen_complex.set(true) - } - - /// Whether we need to generate the binden complex type - pub fn need_bindegen_complex_type(&self) -> bool { - self.generated_bindegen_complex.get() - } - - /// Compute whether we can derive debug. - fn compute_cannot_derive_debug(&mut self) { - let _t = self.timer("compute_cannot_derive_debug"); - assert!(self.cannot_derive_debug.is_none()); - if self.options.derive_debug { - self.cannot_derive_debug = Some(analyze::(self)); - } - } - - /// Look up whether the item with `id` can - /// derive debug or not. - pub fn lookup_can_derive_debug>(&self, id: Id) -> bool { - let id = id.into(); - assert!( - self.in_codegen_phase(), - "We only compute can_derive_debug when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` can - // derive debug or not. - !self.cannot_derive_debug.as_ref().unwrap().contains(&id) - } - - /// Compute whether we can derive default. - fn compute_cannot_derive_default(&mut self) { - let _t = self.timer("compute_cannot_derive_default"); - assert!(self.cannot_derive_default.is_none()); - if self.options.derive_default { - self.cannot_derive_default = - Some(analyze::(self)); - } - } - - /// Look up whether the item with `id` can - /// derive default or not. - pub fn lookup_can_derive_default>(&self, id: Id) -> bool { - let id = id.into(); - assert!( - self.in_codegen_phase(), - "We only compute can_derive_default when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` can - // derive default or not. - !self.cannot_derive_default.as_ref().unwrap().contains(&id) - } - - /// Compute whether we can derive copy. - fn compute_cannot_derive_copy(&mut self) { - let _t = self.timer("compute_cannot_derive_copy"); - assert!(self.cannot_derive_copy.is_none()); - self.cannot_derive_copy = Some(analyze::(self)); - } - - /// Compute whether we can derive hash. - fn compute_cannot_derive_hash(&mut self) { - let _t = self.timer("compute_cannot_derive_hash"); - assert!(self.cannot_derive_hash.is_none()); - if self.options.derive_hash { - self.cannot_derive_hash = Some(analyze::(self)); - } - } - - /// Look up whether the item with `id` can - /// derive hash or not. - pub fn lookup_can_derive_hash>(&self, id: Id) -> bool { - let id = id.into(); - assert!( - self.in_codegen_phase(), - "We only compute can_derive_debug when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` can - // derive hash or not. - !self.cannot_derive_hash.as_ref().unwrap().contains(&id) - } - - /// Compute whether we can derive PartialOrd, PartialEq or Eq. - fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) { - let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq"); - assert!(self.cannot_derive_partialeq_or_partialord.is_none()); - if self.options.derive_partialord || self.options.derive_partialeq || self.options.derive_eq { - self.cannot_derive_partialeq_or_partialord = Some(analyze::(self)); - } - } - - /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`. - pub fn lookup_can_derive_partialeq_or_partialord>(&self, id: Id) -> CanDerive { - let id = id.into(); - assert!( - self.in_codegen_phase(), - "We only compute can_derive_partialeq_or_partialord when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` can - // derive partialeq or not. - self.cannot_derive_partialeq_or_partialord.as_ref() - .unwrap() - .get(&id) - .cloned() - .unwrap_or(CanDerive::Yes) - } - - /// Look up whether the item with `id` can derive `Copy` or not. - pub fn lookup_can_derive_copy>(&self, id: Id) -> bool { - assert!( - self.in_codegen_phase(), - "We only compute can_derive_debug when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` can - // derive `Copy` or not. - let id = id.into(); - - !self.lookup_has_type_param_in_array(id) && - !self.cannot_derive_copy.as_ref().unwrap().contains(&id) - } - - /// Compute whether the type has type parameter in array. - fn compute_has_type_param_in_array(&mut self) { - let _t = self.timer("compute_has_type_param_in_array"); - assert!(self.has_type_param_in_array.is_none()); - self.has_type_param_in_array = - Some(analyze::(self)); - } - - /// Look up whether the item with `id` has type parameter in array or not. - pub fn lookup_has_type_param_in_array>(&self, id: Id) -> bool { - assert!( - self.in_codegen_phase(), - "We only compute has array when we enter codegen" - ); - - // Look up the computed value for whether the item with `id` has - // type parameter in array or not. - self.has_type_param_in_array.as_ref().unwrap().contains(&id.into()) - } - - /// Compute whether the type has float. - fn compute_has_float(&mut self) { - let _t = self.timer("compute_has_float"); - assert!(self.has_float.is_none()); - if self.options.derive_eq || self.options.derive_ord { - self.has_float = Some(analyze::(self)); - } - } - - /// Look up whether the item with `id` has array or not. - pub fn lookup_has_float>(&self, id: Id) -> bool { - assert!(self.in_codegen_phase(), - "We only compute has float when we enter codegen"); - - // Look up the computed value for whether the item with `id` has - // float or not. - self.has_float.as_ref().unwrap().contains(&id.into()) - } - - /// Check if `--no-partialeq` flag is enabled for this item. - pub fn no_partialeq_by_name(&self, item: &Item) -> bool { - let name = item.canonical_path(self)[1..].join("::"); - self.options().no_partialeq_types.matches(&name) - } - - /// Check if `--no-copy` flag is enabled for this item. - pub fn no_copy_by_name(&self, item: &Item) -> bool { - let name = item.canonical_path(self)[1..].join("::"); - self.options().no_copy_types.matches(&name) - } - - /// Chech if `--no-hash` flag is enabled for this item. - pub fn no_hash_by_name(&self, item: &Item) -> bool { - let name = item.canonical_path(self)[1..].join("::"); - self.options().no_hash_types.matches(&name) - } -} - -/// A builder struct for configuring item resolution options. -#[derive(Debug, Copy, Clone)] -pub struct ItemResolver { - id: ItemId, - through_type_refs: bool, - through_type_aliases: bool, -} - -impl ItemId { - /// Create an `ItemResolver` from this item id. - pub fn into_resolver(self) -> ItemResolver { - self.into() - } -} - -impl From for ItemResolver -where - T: Into -{ - fn from(id: T) -> ItemResolver { - ItemResolver::new(id) - } -} - -impl ItemResolver { - /// Construct a new `ItemResolver` from the given id. - pub fn new>(id: Id) -> ItemResolver { - let id = id.into(); - ItemResolver { - id: id, - through_type_refs: false, - through_type_aliases: false, - } - } - - /// Keep resolving through `Type::TypeRef` items. - pub fn through_type_refs(mut self) -> ItemResolver { - self.through_type_refs = true; - self - } - - /// Keep resolving through `Type::Alias` items. - pub fn through_type_aliases(mut self) -> ItemResolver { - self.through_type_aliases = true; - self - } - - /// Finish configuring and perform the actual item resolution. - pub fn resolve(self, ctx: &BindgenContext) -> &Item { - assert!(ctx.collected_typerefs()); - - let mut id = self.id; - loop { - let item = ctx.resolve_item(id); - let ty_kind = item.as_type().map(|t| t.kind()); - match ty_kind { - Some(&TypeKind::ResolvedTypeRef(next_id)) - if self.through_type_refs => { - id = next_id.into(); - } - // We intentionally ignore template aliases here, as they are - // more complicated, and don't represent a simple renaming of - // some type. - Some(&TypeKind::Alias(next_id)) - if self.through_type_aliases => { - id = next_id.into(); - } - _ => return item, - } - } - } -} - -/// A type that we are in the middle of parsing. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct PartialType { - decl: Cursor, - // Just an ItemId, and not a TypeId, because we haven't finished this type - // yet, so there's still time for things to go wrong. - id: ItemId, -} - -impl PartialType { - /// Construct a new `PartialType`. - pub fn new(decl: Cursor, id: ItemId) -> PartialType { - // assert!(decl == decl.canonical()); - PartialType { - decl: decl, - id: id, - } - } - - /// The cursor pointing to this partial type's declaration location. - pub fn decl(&self) -> &Cursor { - &self.decl - } - - /// The item ID allocated for this type. This is *NOT* a key for an entry in - /// the context's item set yet! - pub fn id(&self) -> ItemId { - self.id - } -} - -impl TemplateParameters for PartialType { - fn self_template_params( - &self, - _ctx: &BindgenContext, - ) -> Option> { - // Maybe at some point we will eagerly parse named types, but for now we - // don't and this information is unavailable. - None - } - - fn num_self_template_params(&self, _ctx: &BindgenContext) -> Option { - // Wouldn't it be nice if libclang would reliably give us this - // information‽ - match self.decl().kind() { - clang_sys::CXCursor_ClassTemplate | - clang_sys::CXCursor_FunctionTemplate | - clang_sys::CXCursor_TypeAliasTemplateDecl => { - let mut num_params = 0; - self.decl().visit(|c| { - match c.kind() { - clang_sys::CXCursor_TemplateTypeParameter | - clang_sys::CXCursor_TemplateTemplateParameter | - clang_sys::CXCursor_NonTypeTemplateParameter => { - num_params += 1; - } - _ => {} - }; - clang_sys::CXChildVisit_Continue - }); - Some(num_params) - } - _ => None, - } - } -} diff --git a/src/ir/derive.rs b/src/ir/derive.rs deleted file mode 100644 index b0a6912f8d..0000000000 --- a/src/ir/derive.rs +++ /dev/null @@ -1,196 +0,0 @@ -//! Traits for determining whether we can derive traits for a thing or not. -//! -//! These traits tend to come in pairs: -//! -//! 1. A "trivial" version, whose implementations aren't allowed to recursively -//! look at other types or the results of fix point analyses. -//! -//! 2. A "normal" version, whose implementations simply query the results of a -//! fix point analysis. -//! -//! The former is used by the analyses when creating the results queried by the -//! second. - -use super::context::BindgenContext; - -use std::cmp; -use std::ops; - -/// A trait that encapsulates the logic for whether or not we can derive `Debug` -/// for a given thing. -pub trait CanDeriveDebug { - /// Return `true` if `Debug` can be derived for this thing, `false` - /// otherwise. - fn can_derive_debug(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can trivially -/// derive `Debug` without looking at any other types or the results of a fix -/// point analysis. This is a helper trait for the fix point analysis. -pub trait CanTriviallyDeriveDebug { - /// Return `true` if `Debug` can trivially be derived for this thing, - /// `false` otherwise. - fn can_trivially_derive_debug(&self) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive `Copy` -/// for a given thing. -pub trait CanDeriveCopy<'a> { - /// Return `true` if `Copy` can be derived for this thing, `false` - /// otherwise. - fn can_derive_copy(&'a self, ctx: &'a BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can trivially -/// derive `Copy` without looking at any other types or results of fix point -/// analsyses. This is a helper trait for fix point analysis. -pub trait CanTriviallyDeriveCopy { - /// Return `true` if `Copy` can be trivially derived for this thing, `false` - /// otherwise. - fn can_trivially_derive_copy(&self) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive -/// `Default` for a given thing. -pub trait CanDeriveDefault { - /// Return `true` if `Default` can be derived for this thing, `false` - /// otherwise. - fn can_derive_default(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can trivially -/// derive `Default` without looking at any other types or results of fix point -/// analyses. This is a helper trait for the fix point analysis. -pub trait CanTriviallyDeriveDefault { - /// Return `true` if `Default` can trivially derived for this thing, `false` - /// otherwise. - fn can_trivially_derive_default(&self) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive `Hash` -/// for a given thing. -pub trait CanDeriveHash { - /// Return `true` if `Hash` can be derived for this thing, `false` - /// otherwise. - fn can_derive_hash(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive -/// `PartialEq` for a given thing. -pub trait CanDerivePartialEq { - /// Return `true` if `PartialEq` can be derived for this thing, `false` - /// otherwise. - fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive -/// `PartialOrd` for a given thing. -pub trait CanDerivePartialOrd { - /// Return `true` if `PartialOrd` can be derived for this thing, `false` - /// otherwise. - fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive `Eq` -/// for a given thing. -pub trait CanDeriveEq { - /// Return `true` if `Eq` can be derived for this thing, `false` otherwise. - fn can_derive_eq(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive `Ord` -/// for a given thing. -pub trait CanDeriveOrd { - /// Return `true` if `Ord` can be derived for this thing, `false` otherwise. - fn can_derive_ord(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can derive `Hash` -/// without looking at any other types or the results of any fix point -/// analyses. This is a helper trait for the fix point analysis. -pub trait CanTriviallyDeriveHash { - /// Return `true` if `Hash` can trivially be derived for this thing, `false` - /// otherwise. - fn can_trivially_derive_hash(&self) -> bool; -} - -/// A trait that encapsulates the logic for whether or not we can trivially -/// derive `PartialEq` or `PartialOrd` without looking at any other types or -/// results of fix point analyses. This is a helper for the fix point analysis. -pub trait CanTriviallyDerivePartialEqOrPartialOrd { - /// Return `Yes` if `PartialEq` or `PartialOrd` can trivially be derived - /// for this thing. - fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive; -} - -/// Whether it is possible or not to automatically derive trait for an item. -/// -/// ```ignore -/// No -/// ^ -/// | -/// ArrayTooLarge -/// ^ -/// | -/// Yes -/// ``` -/// -/// Initially we assume that we can derive trait for all types and then -/// update our understanding as we learn more about each type. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)] -pub enum CanDerive { - /// No, we cannot. - No, - - /// The only thing that stops us from automatically deriving is that - /// array with more than maximum number of elements is used. - /// - /// This means we probably can "manually" implement such trait. - ArrayTooLarge, - - /// Yes, we can derive automatically. - Yes, -} - -impl Default for CanDerive { - fn default() -> CanDerive { - CanDerive::Yes - } -} - -impl cmp::PartialOrd for CanDerive { - fn partial_cmp(&self, rhs: &Self) -> Option { - use self::CanDerive::*; - - let ordering = match (*self, *rhs) { - (x, y) if x == y => cmp::Ordering::Equal, - (No, _) => cmp::Ordering::Greater, - (_, No) => cmp::Ordering::Less, - (ArrayTooLarge, _) => cmp::Ordering::Greater, - (_, ArrayTooLarge) => cmp::Ordering::Less, - _ => unreachable!() - }; - Some(ordering) - } -} - -impl CanDerive { - /// Take the least upper bound of `self` and `rhs`. - pub fn join(self, rhs: Self) -> Self { - cmp::max(self, rhs) - } -} - -impl ops::BitOr for CanDerive { - type Output = Self; - - fn bitor(self, rhs: Self) -> Self::Output { - self.join(rhs) - } -} - -impl ops::BitOrAssign for CanDerive { - fn bitor_assign(&mut self, rhs: Self) { - *self = self.join(rhs) - } -} diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs deleted file mode 100644 index 4ae311e21f..0000000000 --- a/src/ir/enum_ty.rs +++ /dev/null @@ -1,253 +0,0 @@ -//! Intermediate representation for C/C++ enumerations. - -use super::context::{BindgenContext, TypeId}; -use super::item::Item; -use super::ty::TypeKind; -use clang; -use ir::annotations::Annotations; -use ir::item::ItemCanonicalPath; -use parse::{ClangItemParser, ParseError}; - -/// An enum representing custom handling that can be given to a variant. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum EnumVariantCustomBehavior { - /// This variant will be a module containing constants. - ModuleConstify, - /// This variant will be constified, that is, forced to generate a constant. - Constify, - /// This variant will be hidden entirely from the resulting enum. - Hide, -} - -/// A C/C++ enumeration. -#[derive(Debug)] -pub struct Enum { - /// The representation used for this enum; it should be an `IntKind` type or - /// an alias to one. - /// - /// It's `None` if the enum is a forward declaration and isn't defined - /// anywhere else, see `tests/headers/func_ptr_in_struct.h`. - repr: Option, - - /// The different variants, with explicit values. - variants: Vec, -} - -impl Enum { - /// Construct a new `Enum` with the given representation and variants. - pub fn new(repr: Option, variants: Vec) -> Self { - Enum { - repr, - variants, - } - } - - /// Get this enumeration's representation. - pub fn repr(&self) -> Option { - self.repr - } - - /// Get this enumeration's variants. - pub fn variants(&self) -> &[EnumVariant] { - &self.variants - } - - /// Construct an enumeration from the given Clang type. - pub fn from_ty( - ty: &clang::Type, - ctx: &mut BindgenContext, - ) -> Result { - use clang_sys::*; - debug!("Enum::from_ty {:?}", ty); - - if ty.kind() != CXType_Enum { - return Err(ParseError::Continue); - } - - let declaration = ty.declaration().canonical(); - let repr = declaration.enum_type().and_then(|et| { - Item::from_ty(&et, declaration, None, ctx).ok() - }); - let mut variants = vec![]; - - // Assume signedness since the default type by the C standard is an int. - let is_signed = repr.and_then( - |r| ctx.resolve_type(r).safe_canonical_type(ctx), - ).map_or(true, |ty| match *ty.kind() { - TypeKind::Int(ref int_kind) => int_kind.is_signed(), - ref other => { - panic!("Since when enums can be non-integers? {:?}", other) - } - }); - - let type_name = ty.spelling(); - let type_name = if type_name.is_empty() { - None - } else { - Some(type_name) - }; - let type_name = type_name.as_ref().map(String::as_str); - - let definition = declaration.definition().unwrap_or(declaration); - definition.visit(|cursor| { - if cursor.kind() == CXCursor_EnumConstantDecl { - let value = if is_signed { - cursor.enum_val_signed().map(EnumVariantValue::Signed) - } else { - cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned) - }; - if let Some(val) = value { - let name = cursor.spelling(); - let annotations = Annotations::new(&cursor); - let custom_behavior = ctx.parse_callbacks() - .and_then(|callbacks| { - callbacks.enum_variant_behavior(type_name, &name, val) - }) - .or_else(|| { - let annotations = annotations.as_ref()?; - if annotations.hide() { - Some(EnumVariantCustomBehavior::Hide) - } else if annotations.constify_enum_variant() { - Some(EnumVariantCustomBehavior::Constify) - } else { - None - } - }); - - let name = ctx.parse_callbacks() - .and_then(|callbacks| { - callbacks.enum_variant_name(type_name, &name, val) - }) - .or_else(|| { - annotations.as_ref()?.use_instead_of()?.last().cloned() - }) - .unwrap_or(name); - - let comment = cursor.raw_comment(); - variants.push(EnumVariant::new( - name, - comment, - val, - custom_behavior, - )); - } - } - CXChildVisit_Continue - }); - Ok(Enum::new(repr, variants)) - } - - /// Whether the enum should be a bitfield - pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool { - let path = item.canonical_path(ctx); - let enum_ty = item.expect_type(); - - ctx.options().bitfield_enums.matches(&path[1..].join("::")) || - (enum_ty.name().is_none() && - self.variants().iter().any(|v| { - ctx.options().bitfield_enums.matches(&v.name()) - })) - } - - /// Whether the enum should be an constified enum module - pub fn is_constified_enum_module( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> bool { - let path = item.canonical_path(ctx); - let enum_ty = item.expect_type(); - - ctx.options().constified_enum_modules.matches(&path[1..].join("::")) || - (enum_ty.name().is_none() && - self.variants().iter().any(|v| { - ctx.options().constified_enum_modules.matches(&v.name()) - })) - } - - /// Whether the enum should be a Rust enum - pub fn is_rustified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool { - let path = item.canonical_path(ctx); - let enum_ty = item.expect_type(); - - ctx.options().rustified_enums.matches(&path[1..].join("::")) || - (enum_ty.name().is_none() && - self.variants().iter().any(|v| { - ctx.options().rustified_enums.matches(&v.name()) - })) - } -} - -/// A single enum variant, to be contained only in an enum. -#[derive(Debug)] -pub struct EnumVariant { - /// The name of the variant. - name: String, - - /// An optional doc comment. - comment: Option, - - /// The integer value of the variant. - val: EnumVariantValue, - - /// The custom behavior this variant may have, if any. - custom_behavior: Option, -} - -/// A constant value assigned to an enumeration variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum EnumVariantValue { - /// A signed constant. - Signed(i64), - - /// An unsigned constant. - Unsigned(u64), -} - -impl EnumVariant { - /// Construct a new enumeration variant from the given parts. - pub fn new( - name: String, - comment: Option, - val: EnumVariantValue, - custom_behavior: Option, - ) -> Self { - EnumVariant { - name, - comment, - val, - custom_behavior, - } - } - - /// Get this variant's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this variant's value. - pub fn val(&self) -> EnumVariantValue { - self.val - } - - /// Get this variant's documentation. - pub fn comment(&self) -> Option<&str> { - self.comment.as_ref().map(|s| &**s) - } - - /// Returns whether this variant should be enforced to be a constant by code - /// generation. - pub fn force_constification(&self) -> bool { - self.custom_behavior.map_or(false, |b| { - b == EnumVariantCustomBehavior::Constify - }) - } - - /// Returns whether the current variant should be hidden completely from the - /// resulting rust enum. - pub fn hidden(&self) -> bool { - self.custom_behavior.map_or(false, |b| { - b == EnumVariantCustomBehavior::Hide - }) - } -} diff --git a/src/ir/function.rs b/src/ir/function.rs deleted file mode 100644 index 602de80ce3..0000000000 --- a/src/ir/function.rs +++ /dev/null @@ -1,593 +0,0 @@ -//! Intermediate representation for C/C++ functions and methods. - -use super::comp::MethodKind; -use super::context::{BindgenContext, TypeId}; -use super::dot::DotAttributes; -use super::item::Item; -use super::traversal::{EdgeKind, Trace, Tracer}; -use super::ty::TypeKind; -use clang; -use clang_sys::{self, CXCallingConv}; -use ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash, - CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use quote; -use std::io; - -const RUST_DERIVE_FUNPTR_LIMIT: usize = 12; - -/// What kind of a function are we looking at? -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FunctionKind { - /// A plain, free function. - Function, - /// A method of some kind. - Method(MethodKind), -} - -impl FunctionKind { - fn from_cursor(cursor: &clang::Cursor) -> Option { - // FIXME(emilio): Deduplicate logic with `ir::comp`. - Some(match cursor.kind() { - clang_sys::CXCursor_FunctionDecl => FunctionKind::Function, - clang_sys::CXCursor_Constructor => FunctionKind::Method( - MethodKind::Constructor, - ), - clang_sys::CXCursor_Destructor => FunctionKind::Method( - if cursor.method_is_virtual() { - MethodKind::VirtualDestructor { - pure_virtual: cursor.method_is_pure_virtual(), - } - } else { - MethodKind::Destructor - } - ), - clang_sys::CXCursor_CXXMethod => { - if cursor.method_is_virtual() { - FunctionKind::Method(MethodKind::Virtual { - pure_virtual: cursor.method_is_pure_virtual(), - }) - } else if cursor.method_is_static() { - FunctionKind::Method(MethodKind::Static) - } else { - FunctionKind::Method(MethodKind::Normal) - } - } - _ => return None, - }) - } -} - -/// The style of linkage -#[derive(Debug, Clone, Copy)] -pub enum Linkage { - /// Externally visible and can be linked against - External, - /// Not exposed externally. 'static inline' functions will have this kind of linkage - Internal -} - -/// A function declaration, with a signature, arguments, and argument names. -/// -/// The argument names vector must be the same length as the ones in the -/// signature. -#[derive(Debug)] -pub struct Function { - /// The name of this function. - name: String, - - /// The mangled name, that is, the symbol. - mangled_name: Option, - - /// The id pointing to the current function signature. - signature: TypeId, - - /// The doc comment on the function, if any. - comment: Option, - - /// The kind of function this is. - kind: FunctionKind, - - /// The linkage of the function. - linkage: Linkage, -} - -impl Function { - /// Construct a new function. - pub fn new( - name: String, - mangled_name: Option, - signature: TypeId, - comment: Option, - kind: FunctionKind, - linkage: Linkage - ) -> Self { - Function { - name, - mangled_name, - signature, - comment, - kind, - linkage, - } - } - - /// Get this function's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this function's name. - pub fn mangled_name(&self) -> Option<&str> { - self.mangled_name.as_ref().map(|n| &**n) - } - - /// Get this function's signature type. - pub fn signature(&self) -> TypeId { - self.signature - } - - /// Get this function's kind. - pub fn kind(&self) -> FunctionKind { - self.kind - } - - /// Get this function's linkage. - pub fn linkage(&self) -> Linkage { - self.linkage - } - -} - -impl DotAttributes for Function { - fn dot_attributes( - &self, - _ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - if let Some(ref mangled) = self.mangled_name { - let mangled: String = - mangled.chars().flat_map(|c| c.escape_default()).collect(); - writeln!( - out, - "mangled name{}", - mangled - )?; - } - - Ok(()) - } -} - -/// An ABI extracted from a clang cursor. -#[derive(Debug, Copy, Clone)] -pub enum Abi { - /// The default C ABI. - C, - /// The "stdcall" ABI. - Stdcall, - /// The "fastcall" ABI. - Fastcall, - /// The "thiscall" ABI. - ThisCall, - /// The "aapcs" ABI. - Aapcs, - /// The "win64" ABI. - Win64, - /// An unknown or invalid ABI. - Unknown(CXCallingConv), -} - -impl Abi { - /// Returns whether this Abi is known or not. - fn is_unknown(&self) -> bool { - match *self { - Abi::Unknown(..) => true, - _ => false, - } - } -} - -impl quote::ToTokens for Abi { - fn to_tokens(&self, tokens: &mut quote::Tokens) { - tokens.append_all(match *self { - Abi::C => quote! { "C" }, - Abi::Stdcall => quote! { "stdcall" }, - Abi::Fastcall => quote! { "fastcall" }, - Abi::ThisCall => quote! { "thiscall" }, - Abi::Aapcs => quote! { "aapcs" }, - Abi::Win64 => quote! { "win64" }, - Abi::Unknown(cc) => panic!( - "Cannot turn unknown calling convention to tokens: {:?}", - cc - ), - }); - } -} - -/// A function signature. -#[derive(Debug)] -pub struct FunctionSig { - /// The return type of the function. - return_type: TypeId, - - /// The type of the arguments, optionally with the name of the argument when - /// declared. - argument_types: Vec<(Option, TypeId)>, - - /// Whether this function is variadic. - is_variadic: bool, - - /// The ABI of this function. - abi: Abi, -} - -fn get_abi(cc: CXCallingConv) -> Abi { - use clang_sys::*; - match cc { - CXCallingConv_Default => Abi::C, - CXCallingConv_C => Abi::C, - CXCallingConv_X86StdCall => Abi::Stdcall, - CXCallingConv_X86FastCall => Abi::Fastcall, - CXCallingConv_X86ThisCall => Abi::ThisCall, - CXCallingConv_AAPCS => Abi::Aapcs, - CXCallingConv_X86_64Win64 => Abi::Win64, - other => Abi::Unknown(other), - } -} - -/// Get the mangled name for the cursor's referent. -pub fn cursor_mangling( - ctx: &BindgenContext, - cursor: &clang::Cursor, -) -> Option { - use clang_sys; - - if !ctx.options().enable_mangling { - return None; - } - - // We early return here because libclang may crash in some case - // if we pass in a variable inside a partial specialized template. - // See rust-lang-nursery/rust-bindgen#67, and rust-lang-nursery/rust-bindgen#462. - if cursor.is_in_non_fully_specialized_template() { - return None; - } - - let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor; - if let Ok(mut manglings) = cursor.cxx_manglings() { - while let Some(m) = manglings.pop() { - // Only generate the destructor group 1, see below. - if is_destructor && !m.ends_with("D1Ev") { - continue; - } - - return Some(m); - } - } - - let mut mangling = cursor.mangling(); - if mangling.is_empty() { - return None; - } - - if is_destructor { - // With old (3.8-) libclang versions, and the Itanium ABI, clang returns - // the "destructor group 0" symbol, which means that it'll try to free - // memory, which definitely isn't what we want. - // - // Explicitly force the destructor group 1 symbol. - // - // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special - // for the reference, and http://stackoverflow.com/a/6614369/1091587 for - // a more friendly explanation. - // - // We don't need to do this for constructors since clang seems to always - // have returned the C1 constructor. - // - // FIXME(emilio): Can a legit symbol in other ABIs end with this string? - // I don't think so, but if it can this would become a linker error - // anyway, not an invalid free at runtime. - // - // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with - // time. - if mangling.ends_with("D0Ev") { - let new_len = mangling.len() - 4; - mangling.truncate(new_len); - mangling.push_str("D1Ev"); - } - } - - Some(mangling) -} - -impl FunctionSig { - /// Construct a new function signature. - pub fn new( - return_type: TypeId, - arguments: Vec<(Option, TypeId)>, - is_variadic: bool, - abi: Abi, - ) -> Self { - FunctionSig { - return_type: return_type, - argument_types: arguments, - is_variadic: is_variadic, - abi: abi, - } - } - - /// Construct a new function signature from the given Clang type. - pub fn from_ty( - ty: &clang::Type, - cursor: &clang::Cursor, - ctx: &mut BindgenContext, - ) -> Result { - use clang_sys::*; - debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor); - - // Skip function templates - if cursor.kind() == CXCursor_FunctionTemplate { - return Err(ParseError::Continue); - } - - // Don't parse operatorxx functions in C++ - let spelling = cursor.spelling(); - if spelling.starts_with("operator") { - return Err(ParseError::Continue); - } - - let cursor = if cursor.is_valid() { - *cursor - } else { - ty.declaration() - }; - - let mut args: Vec<_> = match cursor.kind() { - CXCursor_FunctionDecl | - CXCursor_Constructor | - CXCursor_CXXMethod | - CXCursor_ObjCInstanceMethodDecl | - CXCursor_ObjCClassMethodDecl => { - // For CXCursor_FunctionDecl, cursor.args() is the reliable way - // to get parameter names and types. - cursor - .args() - .unwrap() - .iter() - .map(|arg| { - let arg_ty = arg.cur_type(); - let name = arg.spelling(); - let name = - if name.is_empty() { None } else { Some(name) }; - let ty = Item::from_ty_or_ref(arg_ty, *arg, None, ctx); - (name, ty) - }) - .collect() - } - _ => { - // For non-CXCursor_FunctionDecl, visiting the cursor's children - // is the only reliable way to get parameter names. - let mut args = vec![]; - cursor.visit(|c| { - if c.kind() == CXCursor_ParmDecl { - let ty = - Item::from_ty_or_ref(c.cur_type(), c, None, ctx); - let name = c.spelling(); - let name = - if name.is_empty() { None } else { Some(name) }; - args.push((name, ty)); - } - CXChildVisit_Continue - }); - args - } - }; - - let is_method = cursor.kind() == CXCursor_CXXMethod; - let is_constructor = cursor.kind() == CXCursor_Constructor; - let is_destructor = cursor.kind() == CXCursor_Destructor; - if (is_constructor || is_destructor || is_method) && - cursor.lexical_parent() != cursor.semantic_parent() - { - // Only parse constructors once. - return Err(ParseError::Continue); - } - - if is_method || is_constructor || is_destructor { - let is_const = is_method && cursor.method_is_const(); - let is_virtual = is_method && cursor.method_is_virtual(); - let is_static = is_method && cursor.method_is_static(); - if !is_static && !is_virtual { - let class = Item::parse(cursor.semantic_parent(), None, ctx) - .expect("Expected to parse the class"); - // The `class` most likely is not finished parsing yet, so use - // the unchecked variant. - let class = class.as_type_id_unchecked(); - - let ptr = - Item::builtin_type(TypeKind::Pointer(class), is_const, ctx); - args.insert(0, (Some("this".into()), ptr)); - } else if is_virtual { - let void = Item::builtin_type(TypeKind::Void, false, ctx); - let ptr = - Item::builtin_type(TypeKind::Pointer(void), false, ctx); - args.insert(0, (Some("this".into()), ptr)); - } - } - - let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl || - cursor.kind() == CXCursor_ObjCClassMethodDecl - { - ty.ret_type().or_else(|| cursor.ret_type()).ok_or( - ParseError::Continue, - )? - } else { - ty.ret_type().ok_or(ParseError::Continue)? - }; - let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx); - let call_conv = ty.call_conv(); - let abi = get_abi(call_conv); - - if abi.is_unknown() { - warn!("Unknown calling convention: {:?}", call_conv); - } - - Ok(Self::new(ret.into(), args, ty.is_variadic(), abi)) - } - - /// Get this function signature's return type. - pub fn return_type(&self) -> TypeId { - self.return_type - } - - /// Get this function signature's argument (name, type) pairs. - pub fn argument_types(&self) -> &[(Option, TypeId)] { - &self.argument_types - } - - /// Get this function signature's ABI. - pub fn abi(&self) -> Abi { - self.abi - } - - /// Is this function signature variadic? - pub fn is_variadic(&self) -> bool { - // Clang reports some functions as variadic when they *might* be - // variadic. We do the argument check because rust doesn't codegen well - // variadic functions without an initial argument. - self.is_variadic && !self.argument_types.is_empty() - } - - /// Are function pointers with this signature able to derive Rust traits? - /// Rust only supports deriving traits for function pointers with a limited - /// number of parameters and a couple ABIs. - /// - /// For more details, see: - /// - /// * https://github.com/rust-lang-nursery/rust-bindgen/issues/547, - /// * https://github.com/rust-lang/rust/issues/38848, - /// * and https://github.com/rust-lang/rust/issues/40158 - pub fn function_pointers_can_derive(&self) -> bool { - if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return false; - } - - match self.abi { - Abi::C | Abi::Unknown(..) => true, - _ => false, - } - } -} - -impl ClangSubItemParser for Function { - fn parse( - cursor: clang::Cursor, - context: &mut BindgenContext, - ) -> Result, ParseError> { - use clang_sys::*; - - let kind = match FunctionKind::from_cursor(&cursor) { - None => return Err(ParseError::Continue), - Some(k) => k, - }; - - debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type()); - - let visibility = cursor.visibility(); - if visibility != CXVisibility_Default { - return Err(ParseError::Continue); - } - - if cursor.access_specifier() == CX_CXXPrivate { - return Err(ParseError::Continue); - } - - if !context.options().generate_inline_functions && - cursor.is_inlined_function() - { - return Err(ParseError::Continue); - } - - let linkage = cursor.linkage(); - let linkage = match linkage { - CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External, - CXLinkage_Internal => Linkage::Internal, - _ => return Err(ParseError::Continue) - }; - - // Grab the signature using Item::from_ty. - let sig = - Item::from_ty(&cursor.cur_type(), cursor, None, context)?; - - let mut name = cursor.spelling(); - assert!(!name.is_empty(), "Empty function name?"); - - if cursor.kind() == CXCursor_Destructor { - // Remove the leading `~`. The alternative to this is special-casing - // code-generation for destructor functions, which seems less than - // ideal. - if name.starts_with('~') { - name.remove(0); - } - - // Add a suffix to avoid colliding with constructors. This would be - // technically fine (since we handle duplicated functions/methods), - // but seems easy enough to handle it here. - name.push_str("_destructor"); - } - - let mut mangled_name = cursor_mangling(context, &cursor); - if mangled_name.as_ref() == Some(&name) { - mangled_name = None; - } - - let comment = cursor.raw_comment(); - - let function = Self::new(name, mangled_name, sig, comment, kind, linkage); - Ok(ParseResult::New(function, Some(cursor))) - } -} - -impl Trace for FunctionSig { - type Extra = (); - - fn trace(&self, _: &BindgenContext, tracer: &mut T, _: &()) - where - T: Tracer, - { - tracer.visit_kind(self.return_type().into(), EdgeKind::FunctionReturn); - - for &(_, ty) in self.argument_types() { - tracer.visit_kind(ty.into(), EdgeKind::FunctionParameter); - } - } -} - -impl CanTriviallyDeriveDebug for FunctionSig { - fn can_trivially_derive_debug(&self) -> bool { - self.function_pointers_can_derive() - } -} - -impl CanTriviallyDeriveHash for FunctionSig { - fn can_trivially_derive_hash(&self) -> bool { - self.function_pointers_can_derive() - } -} - -impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig { - fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive { - if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return CanDerive::No; - } - - match self.abi { - Abi::C | Abi::Unknown(..) => CanDerive::Yes, - _ => CanDerive::No, - } - } -} diff --git a/src/ir/item.rs b/src/ir/item.rs deleted file mode 100644 index 2b3c1b8c41..0000000000 --- a/src/ir/item.rs +++ /dev/null @@ -1,1866 +0,0 @@ -//! Bindgen's core intermediate representation type. - -use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult}; -use super::annotations::Annotations; -use super::comment; -use super::comp::MethodKind; -use super::context::{BindgenContext, ItemId, PartialType, TypeId}; -use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, - CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq}; -use super::dot::DotAttributes; -use super::function::{Function, FunctionKind}; -use super::item_kind::ItemKind; -use super::layout::Opaque; -use super::module::Module; -use super::super::codegen::CONSTIFIED_ENUM_MODULE_REPR_NAME; -use super::template::{AsTemplateParam, TemplateParameters}; -use super::traversal::{EdgeKind, Trace, Tracer}; -use super::ty::{Type, TypeKind}; -use clang; -use clang_sys; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use regex; -use std::cell::{Cell, RefCell}; -use std::collections::BTreeSet; -use std::fmt::Write; -use std::io; -use std::iter; - -/// A trait to get the canonical name from an item. -/// -/// This is the trait that will eventually isolate all the logic related to name -/// mangling and that kind of stuff. -/// -/// This assumes no nested paths, at some point I'll have to make it a more -/// complex thing. -/// -/// This name is required to be safe for Rust, that is, is not expected to -/// return any rust keyword from here. -pub trait ItemCanonicalName { - /// Get the canonical name for this item. - fn canonical_name(&self, ctx: &BindgenContext) -> String; -} - -/// The same, but specifies the path that needs to be followed to reach an item. -/// -/// To contrast with canonical_name, here's an example: -/// -/// ```c++ -/// namespace foo { -/// const BAR = 3; -/// } -/// ``` -/// -/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical -/// name is just `"BAR"`. -pub trait ItemCanonicalPath { - /// Get the namespace-aware canonical path for this item. This means that if - /// namespaces are disabled, you'll get a single item, and otherwise you get - /// the whole path. - fn namespace_aware_canonical_path( - &self, - ctx: &BindgenContext, - ) -> Vec; - - /// Get the canonical path for this item. - fn canonical_path(&self, ctx: &BindgenContext) -> Vec; -} - -/// A trait for determining if some IR thing is opaque or not. -pub trait IsOpaque { - /// Extra context the IR thing needs to determine if it is opaque or not. - type Extra; - - /// Returns `true` if the thing is opaque, and `false` otherwise. - /// - /// May only be called when `ctx` is in the codegen phase. - fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool; -} - -/// A trait for determining if some IR thing has type parameter in array or not. -pub trait HasTypeParamInArray { - /// Returns `true` if the thing has Array, and `false` otherwise. - fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait for determining if some IR thing has float or not. -pub trait HasFloat { - /// Returns `true` if the thing has float, and `false` otherwise. - fn has_float(&self, ctx: &BindgenContext) -> bool; -} - -/// A trait for iterating over an item and its parents and up its ancestor chain -/// up to (but not including) the implicit root module. -pub trait ItemAncestors { - /// Get an iterable over this item's ancestors. - fn ancestors<'a>( - &self, - ctx: &'a BindgenContext, - ) -> ItemAncestorsIter<'a>; -} - -cfg_if! { - if #[cfg(testing_only_extra_assertions)] { - type DebugOnlyItemSet = ItemSet; - } else { - struct DebugOnlyItemSet; - - impl DebugOnlyItemSet { - fn new() -> Self { - DebugOnlyItemSet - } - - fn contains(&self, _id: &ItemId) -> bool { - false - } - - fn insert(&mut self, _id: ItemId) {} - } - } -} - -/// An iterator over an item and its ancestors. -pub struct ItemAncestorsIter<'a> { - item: ItemId, - ctx: &'a BindgenContext, - seen: DebugOnlyItemSet, -} - -impl<'a> ItemAncestorsIter<'a> { - fn new>(ctx: &'a BindgenContext, id: Id) -> Self { - ItemAncestorsIter { - item: id.into(), - ctx: ctx, - seen: DebugOnlyItemSet::new(), - } - } -} - -impl<'a> Iterator for ItemAncestorsIter<'a> { - type Item = ItemId; - - fn next(&mut self) -> Option { - let item = self.ctx.resolve_item(self.item); - - if item.parent_id() == self.item { - None - } else { - self.item = item.parent_id(); - - extra_assert!(!self.seen.contains(&item.id())); - self.seen.insert(item.id()); - - Some(item.id()) - } - } -} - -impl AsTemplateParam for T -where - T: Copy + Into { - type Extra = (); - - fn as_template_param( - &self, - ctx: &BindgenContext, - _: &(), - ) -> Option { - ctx.resolve_item((*self).into()).as_template_param(ctx, &()) - } -} - -impl AsTemplateParam for Item { - type Extra = (); - - fn as_template_param( - &self, - ctx: &BindgenContext, - _: &(), - ) -> Option { - self.kind.as_template_param(ctx, self) - } -} - -impl AsTemplateParam for ItemKind { - type Extra = Item; - - fn as_template_param( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> Option { - match *self { - ItemKind::Type(ref ty) => ty.as_template_param(ctx, item), - ItemKind::Module(..) | - ItemKind::Function(..) | - ItemKind::Var(..) => None, - } - } -} - -impl ItemCanonicalName for T -where - T: Copy + Into -{ - fn canonical_name(&self, ctx: &BindgenContext) -> String { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.resolve_item(*self).canonical_name(ctx) - } -} - -impl ItemCanonicalPath for T - where - T: Copy + Into -{ - fn namespace_aware_canonical_path( - &self, - ctx: &BindgenContext, - ) -> Vec { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.resolve_item(*self).namespace_aware_canonical_path(ctx) - } - - fn canonical_path(&self, ctx: &BindgenContext) -> Vec { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.resolve_item(*self).canonical_path(ctx) - } -} - -impl ItemAncestors for T -where - T: Copy + Into -{ - fn ancestors<'a>( - &self, - ctx: &'a BindgenContext, - ) -> ItemAncestorsIter<'a> { - ItemAncestorsIter::new(ctx, *self) - } -} - -impl ItemAncestors for Item { - fn ancestors<'a>( - &self, - ctx: &'a BindgenContext, - ) -> ItemAncestorsIter<'a> { - self.id().ancestors(ctx) - } -} - -impl Trace for Id -where - Id: Copy + Into -{ - type Extra = (); - - fn trace(&self, ctx: &BindgenContext, tracer: &mut T, extra: &()) - where - T: Tracer, - { - ctx.resolve_item(*self).trace(ctx, tracer, extra); - } -} - -impl Trace for Item { - type Extra = (); - - fn trace(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &()) - where - T: Tracer, - { - // Even if this item is blacklisted/hidden, we want to trace it. It is - // traversal iterators' consumers' responsibility to filter items as - // needed. Generally, this filtering happens in the implementation of - // `Iterator` for `WhitelistedItems`. Fully tracing blacklisted items is - // necessary for things like the template parameter usage analysis to - // function correctly. - - match *self.kind() { - ItemKind::Type(ref ty) => { - // There are some types, like resolved type references, where we - // don't want to stop collecting types even though they may be - // opaque. - if ty.should_be_traced_unconditionally() || - !self.is_opaque(ctx, &()) - { - ty.trace(ctx, tracer, self); - } - } - ItemKind::Function(ref fun) => { - // Just the same way, it has not real meaning for a function to - // be opaque, so we trace across it. - tracer.visit(fun.signature().into()); - } - ItemKind::Var(ref var) => { - tracer.visit_kind(var.ty().into(), EdgeKind::VarType); - } - ItemKind::Module(_) => { - // Module -> children edges are "weak", and we do not want to - // trace them. If we did, then whitelisting wouldn't work as - // expected: everything in every module would end up - // whitelisted. - // - // TODO: make a new edge kind for module -> children edges and - // filter them during whitelisting traversals. - } - } - } -} - -impl CanDeriveDebug for Item { - fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_debug(ctx) - } -} - -impl CanDeriveDefault for Item { - fn can_derive_default(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_default(ctx) - } -} - -impl<'a> CanDeriveCopy<'a> for Item { - fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_copy(ctx) - } -} - -impl CanDeriveHash for Item { - fn can_derive_hash(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_hash(ctx) - } -} - -impl CanDerivePartialOrd for Item { - fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_partialord(ctx) - } -} - -impl CanDerivePartialEq for Item { - fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_partialeq(ctx) - } -} - -impl CanDeriveEq for Item { - fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_eq(ctx) - } -} - -impl CanDeriveOrd for Item { - fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { - self.id().can_derive_ord(ctx) - } -} - -/// An item is the base of the bindgen representation, it can be either a -/// module, a type, a function, or a variable (see `ItemKind` for more -/// information). -/// -/// Items refer to each other by `ItemId`. Every item has its parent's -/// id. Depending on the kind of item this is, it may also refer to other items, -/// such as a compound type item referring to other types. Collectively, these -/// references form a graph. -/// -/// The entry-point to this graph is the "root module": a meta-item used to hold -/// all top-level items. -/// -/// An item may have a comment, and annotations (see the `annotations` module). -/// -/// Note that even though we parse all the types of annotations in comments, not -/// all of them apply to every item. Those rules are described in the -/// `annotations` module. -#[derive(Debug)] -pub struct Item { - /// This item's id. - id: ItemId, - - /// The item's local id, unique only amongst its siblings. Only used for - /// anonymous items. - /// - /// Lazily initialized in local_id(). - /// - /// Note that only structs, unions, and enums get a local type id. In any - /// case this is an implementation detail. - local_id: Cell>, - - /// The next local id to use for a child or template instantiation. - next_child_local_id: Cell, - - /// A cached copy of the canonical name, as returned by `canonical_name`. - /// - /// This is a fairly used operation during codegen so this makes bindgen - /// considerably faster in those cases. - canonical_name_cache: RefCell>, - - /// A doc comment over the item, if any. - comment: Option, - /// Annotations extracted from the doc comment, or the default ones - /// otherwise. - annotations: Annotations, - /// An item's parent id. This will most likely be a class where this item - /// was declared, or a module, etc. - /// - /// All the items have a parent, except the root module, in which case the - /// parent id is its own id. - parent_id: ItemId, - /// The item kind. - kind: ItemKind, -} - -impl AsRef for Item { - fn as_ref(&self) -> &ItemId { - &self.id - } -} - -impl Item { - /// Construct a new `Item`. - pub fn new( - id: ItemId, - comment: Option, - annotations: Option, - parent_id: ItemId, - kind: ItemKind, - ) -> Self { - debug_assert!(id != parent_id || kind.is_module()); - Item { - id: id, - local_id: Cell::new(None), - next_child_local_id: Cell::new(1), - canonical_name_cache: RefCell::new(None), - parent_id: parent_id, - comment: comment, - annotations: annotations.unwrap_or_default(), - kind: kind, - } - } - - /// Construct a new opaque item type. - pub fn new_opaque_type( - with_id: ItemId, - ty: &clang::Type, - ctx: &mut BindgenContext, - ) -> TypeId { - let ty = Opaque::from_clang_ty(ty); - let kind = ItemKind::Type(ty); - let parent = ctx.root_module().into(); - ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None); - with_id.as_type_id_unchecked() - } - - /// Get this `Item`'s identifier. - pub fn id(&self) -> ItemId { - self.id - } - - /// Get this `Item`'s parent's identifier. - /// - /// For the root module, the parent's ID is its own ID. - pub fn parent_id(&self) -> ItemId { - self.parent_id - } - - /// Set this item's parent id. - /// - /// This is only used so replacements get generated in the proper module. - pub fn set_parent_for_replacement>(&mut self, id: Id) { - self.parent_id = id.into(); - } - - /// Returns the depth this item is indented to. - /// - /// FIXME(emilio): This may need fixes for the enums within modules stuff. - pub fn codegen_depth(&self, ctx: &BindgenContext) -> usize { - if !ctx.options().enable_cxx_namespaces { - return 0; - } - - self.ancestors(ctx) - .filter(|id| { - ctx.resolve_item(*id).as_module().map_or(false, |module| { - !module.is_inline() || - ctx.options().conservative_inline_namespaces - }) - }) - .count() + 1 - } - - - /// Get this `Item`'s comment, if it has any, already preprocessed and with - /// the right indentation. - pub fn comment(&self, ctx: &BindgenContext) -> Option { - if !ctx.options().generate_comments { - return None; - } - - self.comment.as_ref().map(|comment| { - comment::preprocess(comment, self.codegen_depth(ctx)) - }) - } - - /// What kind of item is this? - pub fn kind(&self) -> &ItemKind { - &self.kind - } - - /// Get a mutable reference to this item's kind. - pub fn kind_mut(&mut self) -> &mut ItemKind { - &mut self.kind - } - - /// Get an identifier that differentiates this item from its siblings. - /// - /// This should stay relatively stable in the face of code motion outside or - /// below this item's lexical scope, meaning that this can be useful for - /// generating relatively stable identifiers within a scope. - pub fn local_id(&self, ctx: &BindgenContext) -> usize { - if self.local_id.get().is_none() { - let parent = ctx.resolve_item(self.parent_id); - self.local_id.set(Some(parent.next_child_local_id())); - } - self.local_id.get().unwrap() - } - - /// Get an identifier that differentiates a child of this item of other - /// related items. - /// - /// This is currently used for anonymous items, and template instantiation - /// tests, in both cases in order to reduce noise when system headers are at - /// place. - pub fn next_child_local_id(&self) -> usize { - let local_id = self.next_child_local_id.get(); - self.next_child_local_id.set(local_id + 1); - local_id - } - - /// Returns whether this item is a top-level item, from the point of view of - /// bindgen. - /// - /// This point of view changes depending on whether namespaces are enabled - /// or not. That way, in the following example: - /// - /// ```c++ - /// namespace foo { - /// static int var; - /// } - /// ``` - /// - /// `var` would be a toplevel item if namespaces are disabled, but won't if - /// they aren't. - /// - /// This function is used to determine when the codegen phase should call - /// `codegen` on an item, since any item that is not top-level will be - /// generated by its parent. - pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool { - // FIXME: Workaround for some types falling behind when parsing weird - // stl classes, for example. - if ctx.options().enable_cxx_namespaces && self.kind().is_module() && - self.id() != ctx.root_module() - { - return false; - } - - let mut parent = self.parent_id; - loop { - let parent_item = match ctx.resolve_item_fallible(parent) { - Some(item) => item, - None => return false, - }; - - if parent_item.id() == ctx.root_module() { - return true; - } else if ctx.options().enable_cxx_namespaces || - !parent_item.kind().is_module() - { - return false; - } - - parent = parent_item.parent_id(); - } - } - - /// Get a reference to this item's underlying `Type`. Panic if this is some - /// other kind of item. - pub fn expect_type(&self) -> &Type { - self.kind().expect_type() - } - - /// Get a reference to this item's underlying `Type`, or `None` if this is - /// some other kind of item. - pub fn as_type(&self) -> Option<&Type> { - self.kind().as_type() - } - - /// Get a reference to this item's underlying `Function`. Panic if this is - /// some other kind of item. - pub fn expect_function(&self) -> &Function { - self.kind().expect_function() - } - - /// Is this item a module? - pub fn is_module(&self) -> bool { - match self.kind { - ItemKind::Module(..) => true, - _ => false, - } - } - - /// Get this item's annotations. - pub fn annotations(&self) -> &Annotations { - &self.annotations - } - - /// Whether this item should be blacklisted. - /// - /// This may be due to either annotations or to other kind of configuration. - pub fn is_blacklisted(&self, ctx: &BindgenContext) -> bool { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - self.annotations.hide() || - ctx.blacklisted_by_name(&self.canonical_path(ctx), self.id) - } - - /// Is this a reference to another type? - pub fn is_type_ref(&self) -> bool { - self.as_type().map_or(false, |ty| ty.is_type_ref()) - } - - /// Is this item a var type? - pub fn is_var(&self) -> bool { - match *self.kind() { - ItemKind::Var(..) => true, - _ => false, - } - } - - /// Take out item NameOptions - pub fn name<'a>( - &'a self, - ctx: &'a BindgenContext, - ) -> NameOptions<'a> { - NameOptions::new(self, ctx) - } - - /// Get the target item id for name generation. - fn name_target(&self, ctx: &BindgenContext) -> ItemId { - let mut targets_seen = DebugOnlyItemSet::new(); - let mut item = self; - - loop { - extra_assert!(!targets_seen.contains(&item.id())); - targets_seen.insert(item.id()); - - if self.annotations().use_instead_of().is_some() { - return self.id(); - } - - match *item.kind() { - ItemKind::Type(ref ty) => { - match *ty.kind() { - TypeKind::ResolvedTypeRef(inner) => { - item = ctx.resolve_item(inner); - } - TypeKind::TemplateInstantiation(ref inst) => { - item = ctx.resolve_item(inst.template_definition()); - } - _ => return item.id(), - } - } - _ => return item.id(), - } - } - } - - /// Create a fully disambiguated name for an item, including template - /// parameters if it is a type - pub fn full_disambiguated_name(&self, ctx: &BindgenContext) -> String { - let mut s = String::new(); - let level = 0; - self.push_disambiguated_name(ctx, &mut s, level); - s - } - - /// Helper function for full_disambiguated_name - fn push_disambiguated_name( - &self, - ctx: &BindgenContext, - to: &mut String, - level: u8, - ) { - to.push_str(&self.canonical_name(ctx)); - if let ItemKind::Type(ref ty) = *self.kind() { - if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() { - to.push_str(&format!("_open{}_", level)); - for arg in inst.template_arguments() { - arg.into_resolver() - .through_type_refs() - .resolve(ctx) - .push_disambiguated_name(ctx, to, level + 1); - to.push_str("_"); - } - to.push_str(&format!("close{}", level)); - } - } - } - - /// Get this function item's name, or `None` if this item is not a function. - fn func_name(&self) -> Option<&str> { - match *self.kind() { - ItemKind::Function(ref func) => Some(func.name()), - _ => None, - } - } - - /// Get the overload index for this method. If this is not a method, return - /// `None`. - fn overload_index(&self, ctx: &BindgenContext) -> Option { - self.func_name().and_then(|func_name| { - let parent = ctx.resolve_item(self.parent_id()); - if let ItemKind::Type(ref ty) = *parent.kind() { - if let TypeKind::Comp(ref ci) = *ty.kind() { - // All the constructors have the same name, so no need to - // resolve and check. - return ci.constructors() - .iter() - .position(|c| *c == self.id()) - .or_else(|| { - ci.methods() - .iter() - .filter(|m| { - let item = ctx.resolve_item(m.signature()); - let func = item.expect_function(); - func.name() == func_name - }) - .position(|m| m.signature() == self.id()) - }); - } - } - - None - }) - } - - /// Get this item's base name (aka non-namespaced name). - fn base_name(&self, ctx: &BindgenContext) -> String { - if let Some(path) = self.annotations().use_instead_of() { - return path.last().unwrap().clone(); - } - - match *self.kind() { - ItemKind::Var(ref var) => var.name().to_owned(), - ItemKind::Module(ref module) => { - module.name().map(ToOwned::to_owned).unwrap_or_else(|| { - format!("_bindgen_mod_{}", self.exposed_id(ctx)) - }) - } - ItemKind::Type(ref ty) => { - ty.sanitized_name(ctx).map(Into::into).unwrap_or_else(|| { - format!("_bindgen_ty_{}", self.exposed_id(ctx)) - }) - } - ItemKind::Function(ref fun) => { - let mut name = fun.name().to_owned(); - - if let Some(idx) = self.overload_index(ctx) { - if idx > 0 { - write!(&mut name, "{}", idx).unwrap(); - } - } - - name - } - } - } - - /// Get the canonical name without taking into account the replaces - /// annotation. - /// - /// This is the base logic used to implement hiding and replacing via - /// annotations, and also to implement proper name mangling. - /// - /// The idea is that each generated type in the same "level" (read: module - /// or namespace) has a unique canonical name. - /// - /// This name should be derived from the immutable state contained in the - /// type and the parent chain, since it should be consistent. - pub fn real_canonical_name( - &self, - ctx: &BindgenContext, - opt: &NameOptions, - ) -> String { - let target = ctx.resolve_item(self.name_target(ctx)); - - // Short-circuit if the target has an override, and just use that. - if let Some(path) = target.annotations.use_instead_of() { - if ctx.options().enable_cxx_namespaces { - return path.last().unwrap().clone(); - } - return path.join("_").to_owned(); - } - - let base_name = target.base_name(ctx); - - // Named template type arguments are never namespaced, and never - // mangled. - if target.is_template_param(ctx, &()) { - return base_name; - } - - // Concatenate this item's ancestors' names together. - let mut names: Vec<_> = target - .parent_id() - .ancestors(ctx) - .filter(|id| *id != ctx.root_module()) - .take_while(|id| { - // Stop iterating ancestors once we reach a non-inline namespace - // when opt.within_namespaces is set. - !opt.within_namespaces || !ctx.resolve_item(*id).is_module() - }) - .filter(|id| { - if !ctx.options().conservative_inline_namespaces { - if let ItemKind::Module(ref module) = - *ctx.resolve_item(*id).kind() - { - return !module.is_inline(); - } - } - - true - }) - .map(|id| { - let item = ctx.resolve_item(id); - let target = ctx.resolve_item(item.name_target(ctx)); - target.base_name(ctx) - }) - .filter(|name| !name.is_empty()) - .collect(); - - names.reverse(); - - if !base_name.is_empty() { - names.push(base_name); - } - - let name = names.join("_"); - - ctx.rust_mangle(&name).into_owned() - } - - /// The exposed id that represents an unique id among the siblings of a - /// given item. - pub fn exposed_id(&self, ctx: &BindgenContext) -> String { - // Only use local ids for enums, classes, structs and union types. All - // other items use their global id. - let ty_kind = self.kind().as_type().map(|t| t.kind()); - if let Some(ty_kind) = ty_kind { - match *ty_kind { - TypeKind::Comp(..) | - TypeKind::TemplateInstantiation(..) | - TypeKind::Enum(..) => return self.local_id(ctx).to_string(), - _ => {} - } - } - - // Note that this `id_` prefix prevents (really unlikely) collisions - // between the global id and the local id of an item with the same - // parent. - format!("id_{}", self.id().as_usize()) - } - - /// Get a reference to this item's `Module`, or `None` if this is not a - /// `Module` item. - pub fn as_module(&self) -> Option<&Module> { - match self.kind { - ItemKind::Module(ref module) => Some(module), - _ => None, - } - } - - /// Get a mutable reference to this item's `Module`, or `None` if this is - /// not a `Module` item. - pub fn as_module_mut(&mut self) -> Option<&mut Module> { - match self.kind { - ItemKind::Module(ref mut module) => Some(module), - _ => None, - } - } - - /// Returns whether the item is a constified module enum - fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool { - // Do not jump through aliases, except for aliases that point to a type - // with the same name, since we dont generate coe for them. - let item = self.id.into_resolver().through_type_refs().resolve(ctx); - let type_ = match *item.kind() { - ItemKind::Type(ref type_) => type_, - _ => return false, - }; - - match *type_.kind() { - TypeKind::Enum(ref enum_) => { - enum_.is_constified_enum_module(ctx, self) - } - TypeKind::Alias(inner_id) => { - // TODO(emilio): Make this "hop through type aliases that aren't - // really generated" an option in `ItemResolver`? - let inner_item = ctx.resolve_item(inner_id); - let name = item.canonical_name(ctx); - - if inner_item.canonical_name(ctx) == name { - inner_item.is_constified_enum_module(ctx) - } else { - false - } - } - _ => false, - } - } - - /// Is this item of a kind that is enabled for code generation? - pub fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool { - let cc = &ctx.options().codegen_config; - match *self.kind() { - ItemKind::Module(..) => true, - ItemKind::Var(_) => cc.vars, - ItemKind::Type(_) => cc.types, - ItemKind::Function(ref f) => { - match f.kind() { - FunctionKind::Function => cc.functions, - FunctionKind::Method(MethodKind::Constructor) => { - cc.constructors - } - FunctionKind::Method(MethodKind::Destructor) | - FunctionKind::Method(MethodKind::VirtualDestructor { .. }) => { - cc.destructors - } - FunctionKind::Method(MethodKind::Static) | - FunctionKind::Method(MethodKind::Normal) | - FunctionKind::Method(MethodKind::Virtual { .. }) => cc.methods, - } - } - } - } -} - -impl IsOpaque for T -where - T: Copy + Into -{ - type Extra = (); - - fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.resolve_item((*self).into()).is_opaque(ctx, &()) - } -} - -impl IsOpaque for Item { - type Extra = (); - - fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - self.annotations.opaque() || - self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) || - ctx.opaque_by_name(&self.canonical_path(ctx)) - } -} - -impl HasVtable for T -where - T: Copy + Into -{ - fn has_vtable(&self, ctx: &BindgenContext) -> bool { - let id: ItemId = (*self).into(); - id.as_type_id(ctx) - .map_or(false, |id| match ctx.lookup_has_vtable(id) { - HasVtableResult::No => false, - _ => true, - }) - } - - fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool { - let id: ItemId = (*self).into(); - id.as_type_id(ctx) - .map_or(false, |id| match ctx.lookup_has_vtable(id) { - HasVtableResult::SelfHasVtable => true, - _ => false, - }) - } -} - -impl HasVtable for Item { - fn has_vtable(&self, ctx: &BindgenContext) -> bool { - self.id().has_vtable(ctx) - } - - fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool { - self.id().has_vtable_ptr(ctx) - } -} - -impl Sizedness for T -where - T: Copy + Into -{ - fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult { - let id: ItemId = (*self).into(); - id.as_type_id(ctx) - .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id)) - } -} - -impl Sizedness for Item { - fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult { - self.id().sizedness(ctx) - } -} - -impl HasTypeParamInArray for T -where - T: Copy + Into -{ - fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.lookup_has_type_param_in_array(*self) - } -} - -impl HasTypeParamInArray for Item { - fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - ctx.lookup_has_type_param_in_array(self.id()) - } -} - -impl HasFloat for T -where - T: Copy + Into -{ - fn has_float(&self, ctx: &BindgenContext) -> bool { - debug_assert!(ctx.in_codegen_phase(), - "You're not supposed to call this yet"); - ctx.lookup_has_float(*self) - } -} - -impl HasFloat for Item { - fn has_float(&self, ctx: &BindgenContext) -> bool { - debug_assert!(ctx.in_codegen_phase(), - "You're not supposed to call this yet"); - ctx.lookup_has_float(self.id()) - } -} - -/// A set of items. -pub type ItemSet = BTreeSet; - -impl DotAttributes for Item { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!( - out, - "{:?} - name{}", - self.id, - self.name(ctx).get() - )?; - - if self.is_opaque(ctx, &()) { - writeln!(out, "opaquetrue")?; - } - - self.kind.dot_attributes(ctx, out) - } -} - -impl TemplateParameters for T -where - T: Copy + Into -{ - fn self_template_params( - &self, - ctx: &BindgenContext, - ) -> Option> { - ctx.resolve_item_fallible(*self).and_then(|item| { - item.self_template_params(ctx) - }) - } -} - -impl TemplateParameters for Item { - fn self_template_params( - &self, - ctx: &BindgenContext, - ) -> Option> { - self.kind.self_template_params(ctx) - } -} - -impl TemplateParameters for ItemKind { - fn self_template_params( - &self, - ctx: &BindgenContext, - ) -> Option> { - match *self { - ItemKind::Type(ref ty) => ty.self_template_params(ctx), - // If we start emitting bindings to explicitly instantiated - // functions, then we'll need to check ItemKind::Function for - // template params. - ItemKind::Function(_) | - ItemKind::Module(_) | - ItemKind::Var(_) => None, - } - } -} - -// An utility function to handle recursing inside nested types. -fn visit_child( - cur: clang::Cursor, - id: ItemId, - ty: &clang::Type, - parent_id: Option, - ctx: &mut BindgenContext, - result: &mut Result, -) -> clang_sys::CXChildVisitResult { - use clang_sys::*; - if result.is_ok() { - return CXChildVisit_Break; - } - - *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx); - - match *result { - Ok(..) => CXChildVisit_Break, - Err(ParseError::Recurse) => { - cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result)); - CXChildVisit_Continue - } - Err(ParseError::Continue) => CXChildVisit_Continue, - } -} - -impl ClangItemParser for Item { - fn builtin_type( - kind: TypeKind, - is_const: bool, - ctx: &mut BindgenContext, - ) -> TypeId { - // Feel free to add more here, I'm just lazy. - match kind { - TypeKind::Void | - TypeKind::Int(..) | - TypeKind::Pointer(..) | - TypeKind::Float(..) => {} - _ => panic!("Unsupported builtin type"), - } - - let ty = Type::new(None, None, kind, is_const); - let id = ctx.next_item_id(); - let module = ctx.root_module().into(); - ctx.add_item( - Item::new(id, None, None, module, ItemKind::Type(ty)), - None, - None, - ); - id.as_type_id_unchecked() - } - - - fn parse( - cursor: clang::Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> Result { - use ir::function::Function; - use ir::module::Module; - use ir::var::Var; - use clang_sys::*; - - if !cursor.is_valid() { - return Err(ParseError::Continue); - } - - let comment = cursor.raw_comment(); - let annotations = Annotations::new(&cursor); - - let current_module = ctx.current_module().into(); - let relevant_parent_id = parent_id.unwrap_or(current_module); - - macro_rules! try_parse { - ($what:ident) => { - match $what::parse(cursor, ctx) { - Ok(ParseResult::New(item, declaration)) => { - let id = ctx.next_item_id(); - - ctx.add_item(Item::new(id, comment, annotations, - relevant_parent_id, - ItemKind::$what(item)), - declaration, - Some(cursor)); - return Ok(id); - } - Ok(ParseResult::AlreadyResolved(id)) => { - return Ok(id); - } - Err(ParseError::Recurse) => return Err(ParseError::Recurse), - Err(ParseError::Continue) => {}, - } - } - } - - try_parse!(Module); - - // NOTE: Is extremely important to parse functions and vars **before** - // types. Otherwise we can parse a function declaration as a type - // (which is legal), and lose functions to generate. - // - // In general, I'm not totally confident this split between - // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but - // I guess we can try. - try_parse!(Function); - try_parse!(Var); - - // Types are sort of special, so to avoid parsing template classes - // twice, handle them separately. - { - let definition = cursor.definition(); - let applicable_cursor = definition.unwrap_or(cursor); - - - let relevant_parent_id = match definition { - Some(definition) => { - if definition != cursor { - ctx.add_semantic_parent(definition, relevant_parent_id); - return Ok(Item::from_ty_or_ref( - applicable_cursor.cur_type(), - cursor, - parent_id, - ctx, - ).into()); - } - ctx.known_semantic_parent(definition) - .or(parent_id) - .unwrap_or(ctx.current_module().into()) - } - None => relevant_parent_id, - }; - - match Item::from_ty( - &applicable_cursor.cur_type(), - applicable_cursor, - Some(relevant_parent_id), - ctx, - ) { - Ok(ty) => return Ok(ty.into()), - Err(ParseError::Recurse) => return Err(ParseError::Recurse), - Err(ParseError::Continue) => {} - } - } - - // Guess how does clang treat extern "C" blocks? - if cursor.kind() == CXCursor_UnexposedDecl { - Err(ParseError::Recurse) - } else { - // We whitelist cursors here known to be unhandled, to prevent being - // too noisy about this. - match cursor.kind() { - CXCursor_MacroDefinition | - CXCursor_MacroExpansion | - CXCursor_UsingDeclaration | - CXCursor_UsingDirective | - CXCursor_StaticAssert | - CXCursor_InclusionDirective => { - debug!( - "Unhandled cursor kind {:?}: {:?}", - cursor.kind(), - cursor - ); - } - _ => { - // ignore toplevel operator overloads - let spelling = cursor.spelling(); - if !spelling.starts_with("operator") { - error!( - "Unhandled cursor kind {:?}: {:?}", - cursor.kind(), - cursor - ); - } - } - } - - Err(ParseError::Continue) - } - } - - fn from_ty_or_ref( - ty: clang::Type, - location: clang::Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> TypeId { - let id = ctx.next_item_id(); - Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx) - } - - /// Parse a C++ type. If we find a reference to a type that has not been - /// defined yet, use `UnresolvedTypeRef` as a placeholder. - /// - /// This logic is needed to avoid parsing items with the incorrect parent - /// and it's sort of complex to explain, so I'll just point to - /// `tests/headers/typeref.hpp` to see the kind of constructs that forced - /// this. - /// - /// Typerefs are resolved once parsing is completely done, see - /// `BindgenContext::resolve_typerefs`. - fn from_ty_or_ref_with_id( - potential_id: ItemId, - ty: clang::Type, - location: clang::Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> TypeId { - debug!( - "from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}", - potential_id, - ty, - location, - parent_id - ); - - if ctx.collected_typerefs() { - debug!("refs already collected, resolving directly"); - return Item::from_ty_with_id( - potential_id, - &ty, - location, - parent_id, - ctx, - ).unwrap_or_else( - |_| Item::new_opaque_type(potential_id, &ty, ctx), - ); - } - - if let Some(ty) = ctx.builtin_or_resolved_ty( - potential_id, - parent_id, - &ty, - Some(location), - ) - { - debug!("{:?} already resolved: {:?}", ty, location); - return ty; - } - - debug!("New unresolved type reference: {:?}, {:?}", ty, location); - - let is_const = ty.is_const(); - let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id); - let current_module = ctx.current_module(); - ctx.add_item( - Item::new( - potential_id, - None, - None, - parent_id.unwrap_or(current_module.into()), - ItemKind::Type(Type::new(None, None, kind, is_const)), - ), - Some(clang::Cursor::null()), - None, - ); - potential_id.as_type_id_unchecked() - } - - fn from_ty( - ty: &clang::Type, - location: clang::Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> Result { - let id = ctx.next_item_id(); - Item::from_ty_with_id(id, ty, location, parent_id, ctx) - } - - /// This is one of the trickiest methods you'll find (probably along with - /// some of the ones that handle templates in `BindgenContext`). - /// - /// This method parses a type, given the potential id of that type (if - /// parsing it was correct), an optional location we're scanning, which is - /// critical some times to obtain information, an optional parent item id, - /// that will, if it's `None`, become the current module id, and the - /// context. - fn from_ty_with_id( - id: ItemId, - ty: &clang::Type, - location: clang::Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> Result { - use clang_sys::*; - - debug!( - "Item::from_ty_with_id: {:?}\n\ - \tty = {:?},\n\ - \tlocation = {:?}", - id, - ty, - location - ); - - if ty.kind() == clang_sys::CXType_Unexposed || - location.cur_type().kind() == clang_sys::CXType_Unexposed - { - - if ty.is_associated_type() || - location.cur_type().is_associated_type() - { - return Ok(Item::new_opaque_type(id, ty, ctx)); - } - - if let Some(id) = Item::type_param(Some(id), location, ctx) { - return Ok(id); - } - } - - let decl = { - let decl = ty.declaration(); - decl.definition().unwrap_or(decl) - }; - - let comment = decl.raw_comment().or_else(|| location.raw_comment()); - let annotations = - Annotations::new(&decl).or_else(|| Annotations::new(&location)); - - if let Some(ref annotations) = annotations { - if let Some(ref replaced) = annotations.use_instead_of() { - ctx.replace(replaced, id); - } - } - - if let Some(ty) = ctx.builtin_or_resolved_ty( - id, - parent_id, - ty, - Some(location), - ) - { - return Ok(ty); - } - - // First, check we're not recursing. - let mut valid_decl = decl.kind() != CXCursor_NoDeclFound; - let declaration_to_look_for = if valid_decl { - decl.canonical() - } else if location.kind() == CXCursor_ClassTemplate { - valid_decl = true; - location - } else { - decl - }; - - if valid_decl { - if let Some(partial) = ctx.currently_parsed_types().iter().find( - |ty| { - *ty.decl() == declaration_to_look_for - }, - ) - { - debug!("Avoiding recursion parsing type: {:?}", ty); - // Unchecked because we haven't finished this type yet. - return Ok(partial.id().as_type_id_unchecked()); - } - } - - let current_module = ctx.current_module().into(); - let partial_ty = PartialType::new(declaration_to_look_for, id); - if valid_decl { - ctx.begin_parsing(partial_ty); - } - - let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); - let relevant_parent_id = parent_id.unwrap_or(current_module); - let ret = match result { - Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty.as_type_id_unchecked()), - Ok(ParseResult::New(item, declaration)) => { - ctx.add_item( - Item::new( - id, - comment, - annotations, - relevant_parent_id, - ItemKind::Type(item), - ), - declaration, - Some(location), - ); - Ok(id.as_type_id_unchecked()) - } - Err(ParseError::Continue) => Err(ParseError::Continue), - Err(ParseError::Recurse) => { - debug!("Item::from_ty recursing in the ast"); - let mut result = Err(ParseError::Recurse); - - // Need to pop here, otherwise we'll get stuck. - // - // TODO: Find a nicer interface, really. Also, the - // declaration_to_look_for suspiciously shares a lot of - // logic with ir::context, so we should refactor that. - if valid_decl { - let finished = ctx.finish_parsing(); - assert_eq!(*finished.decl(), declaration_to_look_for); - } - - location.visit(|cur| { - visit_child(cur, id, ty, parent_id, ctx, &mut result) - }); - - if valid_decl { - let partial_ty = - PartialType::new(declaration_to_look_for, id); - ctx.begin_parsing(partial_ty); - } - - // If we have recursed into the AST all we know, and we still - // haven't found what we've got, let's just try and make a named - // type. - // - // This is what happens with some template members, for example. - if let Err(ParseError::Recurse) = result { - warn!( - "Unknown type, assuming named template type: \ - id = {:?}; spelling = {}", - id, - ty.spelling() - ); - Item::type_param(Some(id), location, ctx) - .map(Ok) - .unwrap_or(Err(ParseError::Recurse)) - } else { - result - } - } - }; - - if valid_decl { - let partial_ty = ctx.finish_parsing(); - assert_eq!(*partial_ty.decl(), declaration_to_look_for); - } - - ret - } - - /// A named type is a template parameter, e.g., the "T" in Foo. They're - /// always local so it's the only exception when there's no declaration for - /// a type. - fn type_param( - with_id: Option, - location: clang::Cursor, - ctx: &mut BindgenContext, - ) -> Option { - let ty = location.cur_type(); - - debug!( - "Item::type_param:\n\ - \twith_id = {:?},\n\ - \tty = {} {:?},\n\ - \tlocation: {:?}", - with_id, - ty.spelling(), - ty, - location - ); - - if ty.kind() != clang_sys::CXType_Unexposed { - // If the given cursor's type's kind is not Unexposed, then we - // aren't looking at a template parameter. This check may need to be - // updated in the future if they start properly exposing template - // type parameters. - return None; - } - - let ty_spelling = ty.spelling(); - - // Clang does not expose any information about template type parameters - // via their clang::Type, nor does it give us their canonical cursors - // the straightforward way. However, there are three situations from - // which we can find the definition of the template type parameter, if - // the cursor is indeed looking at some kind of a template type - // parameter or use of one: - // - // 1. The cursor is pointing at the template type parameter's - // definition. This is the trivial case. - // - // (kind = TemplateTypeParameter, ...) - // - // 2. The cursor is pointing at a TypeRef whose referenced() cursor is - // situation (1). - // - // (kind = TypeRef, - // referenced = (kind = TemplateTypeParameter, ...), - // ...) - // - // 3. The cursor is pointing at some use of a template type parameter - // (for example, in a FieldDecl), and this cursor has a child cursor - // whose spelling is the same as the parent's type's spelling, and whose - // kind is a TypeRef of the situation (2) variety. - // - // (kind = FieldDecl, - // type = (kind = Unexposed, - // spelling = "T", - // ...), - // children = - // (kind = TypeRef, - // spelling = "T", - // referenced = (kind = TemplateTypeParameter, - // spelling = "T", - // ...), - // ...) - // ...) - // - // TODO: The alternative to this hacky pattern matching would be to - // maintain proper scopes of template parameters while parsing and use - // de Brujin indices to access template parameters, which clang exposes - // in the cursor's type's canonical type's spelling: - // "type-parameter-x-y". That is probably a better approach long-term, - // but maintaining these scopes properly would require more changes to - // the whole libclang -> IR parsing code. - - fn is_template_with_spelling( - refd: &clang::Cursor, - spelling: &str, - ) -> bool { - lazy_static! { - static ref ANON_TYPE_PARAM_RE: regex::Regex = - regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap(); - } - - if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter { - return false; - } - - let refd_spelling = refd.spelling(); - refd_spelling == spelling || - // Allow for anonymous template parameters. - (refd_spelling.is_empty() && ANON_TYPE_PARAM_RE.is_match(spelling.as_ref())) - } - - let definition = - if is_template_with_spelling(&location, &ty_spelling) { - // Situation (1) - location - } else if location.kind() == clang_sys::CXCursor_TypeRef { - // Situation (2) - match location.referenced() { - Some(refd) - if is_template_with_spelling(&refd, &ty_spelling) => { - refd - } - _ => return None, - } - } else { - // Situation (3) - let mut definition = None; - - location.visit(|child| { - let child_ty = child.cur_type(); - if child_ty.kind() == clang_sys::CXCursor_TypeRef && - child_ty.spelling() == ty_spelling - { - match child.referenced() { - Some(refd) - if is_template_with_spelling( - &refd, - &ty_spelling, - ) => { - definition = Some(refd); - return clang_sys::CXChildVisit_Break; - } - _ => {} - } - } - - clang_sys::CXChildVisit_Continue - }); - - if let Some(def) = definition { - def - } else { - return None; - } - }; - assert!(is_template_with_spelling(&definition, &ty_spelling)); - - // Named types are always parented to the root module. They are never - // referenced with namespace prefixes, and they can't inherit anything - // from their parent either, so it is simplest to just hang them off - // something we know will always exist. - let parent = ctx.root_module().into(); - - if let Some(id) = ctx.get_type_param(&definition) { - if let Some(with_id) = with_id { - return Some( - ctx.build_ty_wrapper(with_id, id, Some(parent), &ty), - ); - } else { - return Some(id); - } - } - - // See tests/headers/const_tparam.hpp and - // tests/headers/variadic_tname.hpp. - let name = ty_spelling.replace("const ", "").replace(".", ""); - - let id = with_id.unwrap_or_else(|| ctx.next_item_id()); - let item = Item::new( - id, - None, - None, - parent, - ItemKind::Type(Type::named(name)), - ); - ctx.add_type_param(item, definition); - Some(id.as_type_id_unchecked()) - } -} - -impl ItemCanonicalName for Item { - fn canonical_name(&self, ctx: &BindgenContext) -> String { - debug_assert!( - ctx.in_codegen_phase(), - "You're not supposed to call this yet" - ); - if self.canonical_name_cache.borrow().is_none() { - let in_namespace = ctx.options().enable_cxx_namespaces || - ctx.options().disable_name_namespacing; - - *self.canonical_name_cache.borrow_mut() = if in_namespace { - Some(self.name(ctx).within_namespaces().get()) - } else { - Some(self.name(ctx).get()) - }; - } - return self.canonical_name_cache.borrow().as_ref().unwrap().clone(); - } -} - -impl ItemCanonicalPath for Item { - fn namespace_aware_canonical_path( - &self, - ctx: &BindgenContext, - ) -> Vec { - let mut path = self.canonical_path(ctx); - - // ASSUMPTION: (disable_name_namespacing && cxx_namespaces) - // is equivalent to - // disable_name_namespacing - if ctx.options().disable_name_namespacing { - // Only keep the last item in path - let split_idx = path.len() - 1; - path = path.split_off(split_idx); - } else if !ctx.options().enable_cxx_namespaces { - // Ignore first item "root" - path = vec![path[1..].join("_")]; - } - - if self.is_constified_enum_module(ctx) { - path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into()); - } - - return path; - } - - fn canonical_path(&self, ctx: &BindgenContext) -> Vec { - if let Some(path) = self.annotations().use_instead_of() { - let mut ret = - vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()]; - ret.extend_from_slice(path); - return ret; - } - - let target = ctx.resolve_item(self.name_target(ctx)); - let mut path: Vec<_> = target - .ancestors(ctx) - .chain(iter::once(ctx.root_module().into())) - .map(|id| ctx.resolve_item(id)) - .filter(|item| { - item.id() == target.id() || - item.as_module().map_or(false, |module| { - !module.is_inline() || - ctx.options().conservative_inline_namespaces - }) - }) - .map(|item| { - ctx.resolve_item(item.name_target(ctx)) - .name(ctx) - .within_namespaces() - .get() - }) - .collect(); - path.reverse(); - path - } -} - -/// Builder struct for naming variations, which hold inside different -/// flags for naming options. -#[derive(Debug)] -pub struct NameOptions<'a> { - item: &'a Item, - ctx: &'a BindgenContext, - within_namespaces: bool, -} - -impl<'a> NameOptions<'a> { - /// Construct a new `NameOptions` - pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self { - NameOptions { - item: item, - ctx: ctx, - within_namespaces: false, - } - } - - /// Construct the name without the item's containing C++ namespaces mangled - /// into it. In other words, the item's name within the item's namespace. - pub fn within_namespaces(&mut self) -> &mut Self { - self.within_namespaces = true; - self - } - - /// Construct a name `String` - pub fn get(&self) -> String { - self.item.real_canonical_name(self.ctx, self) - } -} diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs deleted file mode 100644 index 1e755e242a..0000000000 --- a/src/ir/item_kind.rs +++ /dev/null @@ -1,151 +0,0 @@ -//! Different variants of an `Item` in our intermediate representation. - -use super::context::BindgenContext; -use super::dot::DotAttributes; -use super::function::Function; -use super::module::Module; -use super::ty::Type; -use super::var::Var; -use std::io; - -/// A item we parse and translate. -#[derive(Debug)] -pub enum ItemKind { - /// A module, created implicitly once (the root module), or via C++ - /// namespaces. - Module(Module), - - /// A type declared in any of the multiple ways it can be declared. - Type(Type), - - /// A function or method declaration. - Function(Function), - - /// A variable declaration, most likely a static. - Var(Var), -} - -impl ItemKind { - /// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it - /// is some other kind. - pub fn as_module(&self) -> Option<&Module> { - match *self { - ItemKind::Module(ref module) => Some(module), - _ => None, - } - } - - /// Transform our `ItemKind` into a string. - pub fn kind_name(&self) -> &'static str { - match *self { - ItemKind::Module(..) => "Module", - ItemKind::Type(..) => "Type", - ItemKind::Function(..) => "Function", - ItemKind::Var(..) => "Var", - } - } - - /// Is this a module? - pub fn is_module(&self) -> bool { - self.as_module().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Module`, or panic if it - /// is some other kind. - pub fn expect_module(&self) -> &Module { - self.as_module().expect("Not a module") - } - - /// Get a reference to this `ItemKind`'s underying `Function`, or `None` if - /// it is some other kind. - pub fn as_function(&self) -> Option<&Function> { - match *self { - ItemKind::Function(ref func) => Some(func), - _ => None, - } - } - - /// Is this a function? - pub fn is_function(&self) -> bool { - self.as_function().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Function`, or panic if - /// it is some other kind. - pub fn expect_function(&self) -> &Function { - self.as_function().expect("Not a function") - } - - /// Get a reference to this `ItemKind`'s underying `Type`, or `None` if - /// it is some other kind. - pub fn as_type(&self) -> Option<&Type> { - match *self { - ItemKind::Type(ref ty) => Some(ty), - _ => None, - } - } - - /// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None` - /// if it is some other kind. - pub fn as_type_mut(&mut self) -> Option<&mut Type> { - match *self { - ItemKind::Type(ref mut ty) => Some(ty), - _ => None, - } - } - - /// Is this a type? - pub fn is_type(&self) -> bool { - self.as_type().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is - /// some other kind. - pub fn expect_type(&self) -> &Type { - self.as_type().expect("Not a type") - } - - /// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is - /// some other kind. - pub fn as_var(&self) -> Option<&Var> { - match *self { - ItemKind::Var(ref v) => Some(v), - _ => None, - } - } - - /// Is this a variable? - pub fn is_var(&self) -> bool { - self.as_var().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is - /// some other kind. - pub fn expect_var(&self) -> &Var { - self.as_var().expect("Not a var") - } -} - -impl DotAttributes for ItemKind { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!( - out, - "kind{}", - self.kind_name() - )?; - - match *self { - ItemKind::Module(ref module) => module.dot_attributes(ctx, out), - ItemKind::Type(ref ty) => ty.dot_attributes(ctx, out), - ItemKind::Function(ref func) => func.dot_attributes(ctx, out), - ItemKind::Var(ref var) => var.dot_attributes(ctx, out), - } - } -} diff --git a/src/ir/layout.rs b/src/ir/layout.rs deleted file mode 100644 index bc3f8a5a0a..0000000000 --- a/src/ir/layout.rs +++ /dev/null @@ -1,160 +0,0 @@ -//! Intermediate representation for the physical layout of some type. - -use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug, - CanTriviallyDeriveDefault, CanTriviallyDeriveHash, - CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; -use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind}; -use ir::context::BindgenContext; -use clang; -use std::cmp; - -/// A type that represents the struct layout of a type. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Layout { - /// The size (in bytes) of this layout. - pub size: usize, - /// The alignment (in bytes) of this layout. - pub align: usize, - /// Whether this layout's members are packed or not. - pub packed: bool, -} - -#[test] -fn test_layout_for_size() { - use std::mem; - - let ptr_size = mem::size_of::<*mut ()>(); - assert_eq!( - Layout::for_size_internal(ptr_size, ptr_size), - Layout::new(ptr_size, ptr_size) - ); - assert_eq!( - Layout::for_size_internal(ptr_size, 3 * ptr_size), - Layout::new(3 * ptr_size, ptr_size) - ); -} - -impl Layout { - /// Construct a new `Layout` with the given `size` and `align`. It is not - /// packed. - pub fn new(size: usize, align: usize) -> Self { - Layout { - size, - align, - packed: false, - } - } - - fn for_size_internal(ptr_size: usize, size: usize) -> Self { - let mut next_align = 2; - while size % next_align == 0 && next_align <= ptr_size { - next_align *= 2; - } - Layout { - size: size, - align: next_align / 2, - packed: false, - } - } - - /// Creates a non-packed layout for a given size, trying to use the maximum - /// alignment possible. - pub fn for_size(ctx: &BindgenContext, size: usize) -> Self { - Self::for_size_internal(ctx.target_pointer_size(), size) - } - - /// Is this a zero-sized layout? - pub fn is_zero(&self) -> bool { - self.size == 0 && self.align == 0 - } - - /// Construct a zero-sized layout. - pub fn zero() -> Self { - Self::new(0, 0) - } - - /// Get this layout as an opaque type. - pub fn opaque(&self) -> Opaque { - Opaque(*self) - } -} - -/// When we are treating a type as opaque, it is just a blob with a `Layout`. -#[derive(Clone, Debug, PartialEq)] -pub struct Opaque(pub Layout); - -impl Opaque { - /// Construct a new opaque type from the given clang type. - pub fn from_clang_ty(ty: &clang::Type) -> Type { - let layout = Layout::new(ty.size(), ty.align()); - let ty_kind = TypeKind::Opaque; - Type::new(None, Some(layout), ty_kind, false) - } - - /// Return the known rust type we should use to create a correctly-aligned - /// field with this layout. - pub fn known_rust_type_for_array(&self) -> Option<&'static str> { - Some(match self.0.align { - 8 => "u64", - 4 => "u32", - 2 => "u16", - 1 => "u8", - _ => return None, - }) - } - - /// Return the array size that an opaque type for this layout should have if - /// we know the correct type for it, or `None` otherwise. - pub fn array_size(&self) -> Option { - if self.known_rust_type_for_array().is_some() { - Some(self.0.size / cmp::max(self.0.align, 1)) - } else { - None - } - } - - /// Return `true` if this opaque layout's array size will fit within the - /// maximum number of array elements that Rust allows deriving traits - /// with. Return `false` otherwise. - pub fn array_size_within_derive_limit(&self) -> bool { - self.array_size().map_or(false, |size| { - size <= RUST_DERIVE_IN_ARRAY_LIMIT - }) - } -} - -impl CanTriviallyDeriveDebug for Opaque { - fn can_trivially_derive_debug(&self) -> bool { - self.array_size_within_derive_limit() - } -} - -impl CanTriviallyDeriveDefault for Opaque { - fn can_trivially_derive_default(&self) -> bool { - self.array_size_within_derive_limit() - } -} - -impl CanTriviallyDeriveCopy for Opaque { - fn can_trivially_derive_copy(&self) -> bool { - self.array_size_within_derive_limit() - } -} - -impl CanTriviallyDeriveHash for Opaque { - fn can_trivially_derive_hash(&self) -> bool { - self.array_size_within_derive_limit() - } -} - -impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque { - fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive { - self.array_size().map_or(CanDerive::No, |size| { - if size <= RUST_DERIVE_IN_ARRAY_LIMIT { - CanDerive::Yes - } else { - CanDerive::ArrayTooLarge - } - }) - } -} diff --git a/src/ir/mod.rs b/src/ir/mod.rs deleted file mode 100644 index 93894f94db..0000000000 --- a/src/ir/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! The ir module defines bindgen's intermediate representation. -//! -//! Parsing C/C++ generates the IR, while code generation outputs Rust code from -//! the IR. - -pub mod annotations; -pub mod analysis; -pub mod comp; -pub mod comment; -pub mod context; -pub mod derive; -pub mod dot; -pub mod enum_ty; -pub mod function; -pub mod int; -pub mod item; -pub mod item_kind; -pub mod layout; -pub mod module; -pub mod template; -pub mod traversal; -pub mod ty; -pub mod var; -pub mod objc; diff --git a/src/ir/module.rs b/src/ir/module.rs deleted file mode 100644 index af46d4acae..0000000000 --- a/src/ir/module.rs +++ /dev/null @@ -1,95 +0,0 @@ -//! Intermediate representation for modules (AKA C++ namespaces). - -use super::context::BindgenContext; -use super::dot::DotAttributes; -use super::item::ItemSet; -use clang; -use parse::{ClangSubItemParser, ParseError, ParseResult}; -use parse_one; -use std::io; - -/// Whether this module is inline or not. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ModuleKind { - /// This module is not inline. - Normal, - /// This module is inline, as in `inline namespace foo {}`. - Inline, -} - -/// A module, as in, a C++ namespace. -#[derive(Clone, Debug)] -pub struct Module { - /// The name of the module, or none if it's anonymous. - name: Option, - /// The kind of module this is. - kind: ModuleKind, - /// The children of this module, just here for convenience. - children: ItemSet, -} - -impl Module { - /// Construct a new `Module`. - pub fn new(name: Option, kind: ModuleKind) -> Self { - Module { - name: name, - kind: kind, - children: ItemSet::new(), - } - } - - /// Get this module's name. - pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|n| &**n) - } - - /// Get a mutable reference to this module's children. - pub fn children_mut(&mut self) -> &mut ItemSet { - &mut self.children - } - - /// Get this module's children. - pub fn children(&self) -> &ItemSet { - &self.children - } - - /// Whether this namespace is inline. - pub fn is_inline(&self) -> bool { - self.kind == ModuleKind::Inline - } -} - -impl DotAttributes for Module { - fn dot_attributes( - &self, - _ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!(out, "ModuleKind{:?}", self.kind) - } -} - -impl ClangSubItemParser for Module { - fn parse( - cursor: clang::Cursor, - ctx: &mut BindgenContext, - ) -> Result, ParseError> { - use clang_sys::*; - match cursor.kind() { - CXCursor_Namespace => { - let module_id = ctx.module(cursor); - ctx.with_module(module_id, |ctx| { - cursor.visit( - |cursor| parse_one(ctx, cursor, Some(module_id.into())), - ) - }); - - Ok(ParseResult::AlreadyResolved(module_id.into())) - } - _ => Err(ParseError::Continue), - } - } -} diff --git a/src/ir/objc.rs b/src/ir/objc.rs deleted file mode 100644 index 46c0802e87..0000000000 --- a/src/ir/objc.rs +++ /dev/null @@ -1,279 +0,0 @@ -//! Objective C types - -use super::context::{BindgenContext, ItemId}; -use super::function::FunctionSig; -use super::traversal::{Trace, Tracer}; -use super::ty::TypeKind; -use clang; -use clang_sys::CXChildVisit_Continue; -use clang_sys::CXCursor_ObjCCategoryDecl; -use clang_sys::CXCursor_ObjCClassMethodDecl; -use clang_sys::CXCursor_ObjCClassRef; -use clang_sys::CXCursor_ObjCInstanceMethodDecl; -use clang_sys::CXCursor_ObjCProtocolDecl; -use clang_sys::CXCursor_ObjCProtocolRef; -use quote; -use proc_macro2::{Term, Span}; - -/// Objective C interface as used in TypeKind -/// -/// Also protocols and categories are parsed as this type -#[derive(Debug)] -pub struct ObjCInterface { - /// The name - /// like, NSObject - name: String, - - category: Option, - - is_protocol: bool, - - conforms_to: Vec, - - /// List of the methods defined in this interfae - methods: Vec, - - class_methods: Vec, -} - -/// The objective c methods -#[derive(Debug)] -pub struct ObjCMethod { - /// The original method selector name - /// like, dataWithBytes:length: - name: String, - - /// Method name as converted to rust - /// like, dataWithBytes_length_ - rust_name: String, - - signature: FunctionSig, - - /// Is class method? - is_class_method: bool, -} - -impl ObjCInterface { - fn new(name: &str) -> ObjCInterface { - ObjCInterface { - name: name.to_owned(), - category: None, - is_protocol: false, - conforms_to: Vec::new(), - methods: Vec::new(), - class_methods: Vec::new(), - } - } - - /// The name - /// like, NSObject - pub fn name(&self) -> &str { - self.name.as_ref() - } - - /// Formats the name for rust - /// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods - /// and protocols are like protocol_NSObject - pub fn rust_name(&self) -> String { - if let Some(ref cat) = self.category { - format!("{}_{}", self.name(), cat) - } else { - if self.is_protocol { - format!("protocol_{}", self.name()) - } else { - self.name().to_owned() - } - } - } - - /// List of the methods defined in this interface - pub fn methods(&self) -> &Vec { - &self.methods - } - - /// List of the class methods defined in this interface - pub fn class_methods(&self) -> &Vec { - &self.class_methods - } - - /// Parses the Objective C interface from the cursor - pub fn from_ty( - cursor: &clang::Cursor, - ctx: &mut BindgenContext, - ) -> Option { - let name = cursor.spelling(); - let mut interface = Self::new(&name); - - if cursor.kind() == CXCursor_ObjCProtocolDecl { - interface.is_protocol = true; - } - - cursor.visit(|c| { - match c.kind() { - CXCursor_ObjCClassRef => { - if cursor.kind() == CXCursor_ObjCCategoryDecl { - // We are actually a category extension, and we found the reference - // to the original interface, so name this interface approriately - interface.name = c.spelling(); - interface.category = Some(cursor.spelling()); - } - } - CXCursor_ObjCProtocolRef => { - // Gather protocols this interface conforms to - let needle = format!("protocol_{}", c.spelling()); - let items_map = ctx.items(); - debug!("Interface {} conforms to {}, find the item", interface.name, needle); - - for (id, item) in items_map - { - if let Some(ty) = item.as_type() { - match *ty.kind() { - TypeKind::ObjCInterface(ref protocol) => { - if protocol.is_protocol - { - debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name()); - if Some(needle.as_ref()) == ty.name() - { - debug!("Found conforming protocol {:?}", item); - interface.conforms_to.push(*id); - break; - } - } - } - _ => {} - } - } - } - - } - CXCursor_ObjCInstanceMethodDecl | - CXCursor_ObjCClassMethodDecl => { - let name = c.spelling(); - let signature = - FunctionSig::from_ty(&c.cur_type(), &c, ctx) - .expect("Invalid function sig"); - let is_class_method = c.kind() == CXCursor_ObjCClassMethodDecl; - let method = ObjCMethod::new(&name, signature, is_class_method); - interface.add_method(method); - } - _ => {} - } - CXChildVisit_Continue - }); - Some(interface) - } - - fn add_method(&mut self, method: ObjCMethod) { - if method.is_class_method { - self.class_methods.push(method); - } else { - self.methods.push(method); - } - } -} - -impl ObjCMethod { - fn new( - name: &str, - signature: FunctionSig, - is_class_method: bool, - ) -> ObjCMethod { - let split_name: Vec<&str> = name.split(':').collect(); - - let rust_name = split_name.join("_"); - - ObjCMethod { - name: name.to_owned(), - rust_name: rust_name.to_owned(), - signature: signature, - is_class_method: is_class_method, - } - } - - /// The original method selector name - /// like, dataWithBytes:length: - pub fn name(&self) -> &str { - self.name.as_ref() - } - - /// Method name as converted to rust - /// like, dataWithBytes_length_ - pub fn rust_name(&self) -> &str { - self.rust_name.as_ref() - } - - /// Returns the methods signature as FunctionSig - pub fn signature(&self) -> &FunctionSig { - &self.signature - } - - /// Is this a class method? - pub fn is_class_method(&self) -> bool { - self.is_class_method - } - - /// Formats the method call - pub fn format_method_call(&self, args: &[quote::Tokens]) -> quote::Tokens { - let split_name: Vec<_> = self.name - .split(':') - .filter(|p| !p.is_empty()) - .map(|name| Term::new(name, Span::call_site())) - .collect(); - - // No arguments - if args.len() == 0 && split_name.len() == 1 { - let name = &split_name[0]; - return quote! { - #name - }; - } - - // Check right amount of arguments - if args.len() != split_name.len() { - panic!( - "Incorrect method name or arguments for objc method, {:?} vs {:?}", - args, - split_name - ); - } - - // Get arguments without type signatures to pass to `msg_send!` - let mut args_without_types = vec![]; - for arg in args.iter() { - let arg = arg.to_string(); - let name_and_sig: Vec<&str> = arg.split(' ').collect(); - let name = name_and_sig[0]; - args_without_types.push(Term::new(name, Span::call_site())) - }; - - let args = split_name - .into_iter() - .zip(args_without_types) - .map(|(arg, arg_val)| quote! { #arg : #arg_val }); - - quote! { - #( #args )* - } - } -} - -impl Trace for ObjCInterface { - type Extra = (); - - fn trace(&self, context: &BindgenContext, tracer: &mut T, _: &()) - where - T: Tracer, - { - for method in &self.methods { - method.signature.trace(context, tracer, &()); - } - - for class_method in &self.class_methods { - class_method.signature.trace(context, tracer, &()); - } - - for protocol in &self.conforms_to { - tracer.visit(*protocol); - } - } -} diff --git a/src/ir/template.rs b/src/ir/template.rs deleted file mode 100644 index 11a799f4f6..0000000000 --- a/src/ir/template.rs +++ /dev/null @@ -1,358 +0,0 @@ -//! Template declaration and instantiation related things. -//! -//! The nomenclature surrounding templates is often confusing, so here are a few -//! brief definitions: -//! -//! * "Template definition": a class/struct/alias/function definition that takes -//! generic template parameters. For example: -//! -//! ```c++ -//! template -//! class List { -//! // ... -//! }; -//! ``` -//! -//! * "Template instantiation": an instantiation is a use of a template with -//! concrete template arguments. For example, `List`. -//! -//! * "Template specialization": an alternative template definition providing a -//! custom definition for instantiations with the matching template -//! arguments. This C++ feature is unsupported by bindgen. For example: -//! -//! ```c++ -//! template<> -//! class List { -//! // Special layout for int lists... -//! }; -//! ``` - -use super::context::{BindgenContext, ItemId, TypeId}; -use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath}; -use super::traversal::{EdgeKind, Trace, Tracer}; -use clang; -use parse::ClangItemParser; - -/// Template declaration (and such declaration's template parameters) related -/// methods. -/// -/// This trait's methods distinguish between `None` and `Some([])` for -/// declarations that are not templates and template declarations with zero -/// parameters, in general. -/// -/// Consider this example: -/// -/// ```c++ -/// template -/// class Foo { -/// T use_of_t; -/// U use_of_u; -/// -/// template -/// using Bar = V*; -/// -/// class Inner { -/// T x; -/// U y; -/// Bar z; -/// }; -/// -/// template -/// class Lol { -/// // No use of W, but here's a use of T. -/// T t; -/// }; -/// -/// template -/// class Wtf { -/// // X is not used because W is not used. -/// Lol lololol; -/// }; -/// }; -/// -/// class Qux { -/// int y; -/// }; -/// ``` -/// -/// The following table depicts the results of each trait method when invoked on -/// each of the declarations above: -/// -/// +------+----------------------+--------------------------+------------------------+---- -/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ... -/// +------+----------------------+--------------------------+------------------------+---- -/// |Foo | Some([T, U]) | Some(2) | Some([T, U]) | ... -/// |Bar | Some([V]) | Some(1) | Some([T, U, V]) | ... -/// |Inner | None | None | Some([T, U]) | ... -/// |Lol | Some([W]) | Some(1) | Some([T, U, W]) | ... -/// |Wtf | Some([X]) | Some(1) | Some([T, U, X]) | ... -/// |Qux | None | None | None | ... -/// +------+----------------------+--------------------------+------------------------+---- -/// -/// ----+------+-----+----------------------+ -/// ... |Decl. | ... | used_template_params | -/// ----+------+-----+----------------------+ -/// ... |Foo | ... | Some([T, U]) | -/// ... |Bar | ... | Some([V]) | -/// ... |Inner | ... | None | -/// ... |Lol | ... | Some([T]) | -/// ... |Wtf | ... | Some([T]) | -/// ... |Qux | ... | None | -/// ----+------+-----+----------------------+ -pub trait TemplateParameters { - /// Get the set of `ItemId`s that make up this template declaration's free - /// template parameters. - /// - /// Note that these might *not* all be named types: C++ allows - /// constant-value template parameters as well as template-template - /// parameters. Of course, Rust does not allow generic parameters to be - /// anything but types, so we must treat them as opaque, and avoid - /// instantiating them. - fn self_template_params(&self, ctx: &BindgenContext) - -> Option>; - - /// Get the number of free template parameters this template declaration - /// has. - /// - /// Implementations *may* return `Some` from this method when - /// `template_params` returns `None`. This is useful when we only have - /// partial information about the template declaration, such as when we are - /// in the middle of parsing it. - fn num_self_template_params(&self, ctx: &BindgenContext) -> Option { - self.self_template_params(ctx).map(|params| params.len()) - } - - /// Get the complete set of template parameters that can affect this - /// declaration. - /// - /// Note that this item doesn't need to be a template declaration itself for - /// `Some` to be returned here (in contrast to `self_template_params`). If - /// this item is a member of a template declaration, then the parent's - /// template parameters are included here. - /// - /// In the example above, `Inner` depends on both of the `T` and `U` type - /// parameters, even though it is not itself a template declaration and - /// therefore has no type parameters itself. Perhaps it helps to think about - /// how we would fully reference such a member type in C++: - /// `Foo::Inner`. `Foo` *must* be instantiated with template - /// arguments before we can gain access to the `Inner` member type. - fn all_template_params(&self, ctx: &BindgenContext) -> Option> - where - Self: ItemAncestors, - { - let each_self_params: Vec> = self.ancestors(ctx) - .filter_map(|id| id.self_template_params(ctx)) - .collect(); - if each_self_params.is_empty() { - None - } else { - Some( - each_self_params - .into_iter() - .rev() - .flat_map(|params| params) - .collect(), - ) - } - } - - /// Get only the set of template parameters that this item uses. This is a - /// subset of `all_template_params` and does not necessarily contain any of - /// `self_template_params`. - fn used_template_params(&self, ctx: &BindgenContext) -> Option> - where - Self: AsRef, - { - assert!( - ctx.in_codegen_phase(), - "template parameter usage is not computed until codegen" - ); - - let id = *self.as_ref(); - ctx.resolve_item(id).all_template_params(ctx).map( - |all_params| { - all_params - .into_iter() - .filter(|p| ctx.uses_template_parameter(id, *p)) - .collect() - }, - ) - } -} - -/// A trait for things which may or may not be a named template type parameter. -pub trait AsTemplateParam { - /// Any extra information the implementor might need to make this decision. - type Extra; - - /// Convert this thing to the item id of a named template type parameter. - fn as_template_param( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> Option; - - /// Is this a named template type parameter? - fn is_template_param( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> bool { - self.as_template_param(ctx, extra).is_some() - } -} - -/// A concrete instantiation of a generic template. -#[derive(Clone, Debug)] -pub struct TemplateInstantiation { - /// The template definition which this is instantiating. - definition: TypeId, - /// The concrete template arguments, which will be substituted in the - /// definition for the generic template parameters. - args: Vec, -} - -impl TemplateInstantiation { - /// Construct a new template instantiation from the given parts. - pub fn new(definition: TypeId, args: I) -> TemplateInstantiation - where - I: IntoIterator, - { - TemplateInstantiation { - definition, - args: args.into_iter().collect(), - } - } - - /// Get the template definition for this instantiation. - pub fn template_definition(&self) -> TypeId { - self.definition - } - - /// Get the concrete template arguments used in this instantiation. - pub fn template_arguments(&self) -> &[TypeId] { - &self.args[..] - } - - /// Parse a `TemplateInstantiation` from a clang `Type`. - pub fn from_ty( - ty: &clang::Type, - ctx: &mut BindgenContext, - ) -> Option { - use clang_sys::*; - - let template_args = ty.template_args() - .map_or(vec![], |args| { - match ty.canonical_type().template_args() { - Some(canonical_args) => { - let arg_count = args.len(); - args.chain(canonical_args.skip(arg_count)) - .filter(|t| t.kind() != CXType_Invalid) - .map(|t| { - Item::from_ty_or_ref(t, t.declaration(), None, ctx) - }).collect() - } - None => { - args.filter(|t| t.kind() != CXType_Invalid) - .map(|t| { - Item::from_ty_or_ref(t, t.declaration(), None, ctx) - }).collect() - } - } - }); - - let declaration = ty.declaration(); - let definition = - if declaration.kind() == CXCursor_TypeAliasTemplateDecl { - Some(declaration) - } else { - declaration.specialized().or_else(|| { - let mut template_ref = None; - ty.declaration().visit(|child| { - if child.kind() == CXCursor_TemplateRef { - template_ref = Some(child); - return CXVisit_Break; - } - - // Instantiations of template aliases might have the - // TemplateRef to the template alias definition arbitrarily - // deep, so we need to recurse here and not only visit - // direct children. - CXChildVisit_Recurse - }); - - template_ref.and_then(|cur| cur.referenced()) - }) - }; - - let definition = match definition { - Some(def) => def, - None => { - if !ty.declaration().is_builtin() { - warn!( - "Could not find template definition for template \ - instantiation" - ); - } - return None; - } - }; - - let template_definition = - Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx); - - Some(TemplateInstantiation::new( - template_definition, - template_args, - )) - } -} - -impl IsOpaque for TemplateInstantiation { - type Extra = Item; - - /// Is this an opaque template instantiation? - fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { - if self.template_definition().is_opaque(ctx, &()) { - return true; - } - - // TODO(#774): This doesn't properly handle opaque instantiations where - // an argument is itself an instantiation because `canonical_name` does - // not insert the template arguments into the name, ie it for nested - // template arguments it creates "Foo" instead of "Foo". The fully - // correct fix is to make `canonical_{name,path}` include template - // arguments properly. - - let mut path = item.canonical_path(ctx); - let args: Vec<_> = self.template_arguments() - .iter() - .map(|arg| { - let arg_path = arg.canonical_path(ctx); - arg_path[1..].join("::") - }) - .collect(); - { - let last = path.last_mut().unwrap(); - last.push('<'); - last.push_str(&args.join(", ")); - last.push('>'); - } - - ctx.opaque_by_name(&path) - } -} - -impl Trace for TemplateInstantiation { - type Extra = (); - - fn trace(&self, _ctx: &BindgenContext, tracer: &mut T, _: &()) - where - T: Tracer, - { - tracer.visit_kind(self.definition.into(), EdgeKind::TemplateDeclaration); - for arg in self.template_arguments() { - tracer.visit_kind(arg.into(), EdgeKind::TemplateArgument); - } - } -} diff --git a/src/ir/ty.rs b/src/ir/ty.rs deleted file mode 100644 index b42f44240c..0000000000 --- a/src/ir/ty.rs +++ /dev/null @@ -1,1261 +0,0 @@ -//! Everything related to types in our intermediate representation. - -use super::comp::CompInfo; -use super::context::{BindgenContext, ItemId, TypeId}; -use super::dot::DotAttributes; -use super::enum_ty::Enum; -use super::function::FunctionSig; -use super::int::IntKind; -use super::item::{IsOpaque, Item}; -use super::layout::{Layout, Opaque}; -use super::objc::ObjCInterface; -use super::template::{AsTemplateParam, TemplateInstantiation, - TemplateParameters}; -use super::traversal::{EdgeKind, Trace, Tracer}; -use clang::{self, Cursor}; -use parse::{ClangItemParser, ParseError, ParseResult}; -use std::borrow::Cow; -use std::io; - -/// The base representation of a type in bindgen. -/// -/// A type has an optional name, which if present cannot be empty, a `layout` -/// (size, alignment and packedness) if known, a `Kind`, which determines which -/// kind of type it is, and whether the type is const. -#[derive(Debug)] -pub struct Type { - /// The name of the type, or None if it was an unnamed struct or union. - name: Option, - /// The layout of the type, if known. - layout: Option, - /// The inner kind of the type - kind: TypeKind, - /// Whether this type is const-qualified. - is_const: bool, -} - -/// The maximum number of items in an array for which Rust implements common -/// traits, and so if we have a type containing an array with more than this -/// many items, we won't be able to derive common traits on that type. -/// -/// We need type-level integers yesterday :'( -pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32; - -impl Type { - /// Get the underlying `CompInfo` for this type, or `None` if this is some - /// other kind of type. - pub fn as_comp(&self) -> Option<&CompInfo> { - match self.kind { - TypeKind::Comp(ref ci) => Some(ci), - _ => None, - } - } - - /// Get the underlying `CompInfo` for this type as a mutable reference, or - /// `None` if this is some other kind of type. - pub fn as_comp_mut(&mut self) -> Option<&mut CompInfo> { - match self.kind { - TypeKind::Comp(ref mut ci) => Some(ci), - _ => None, - } - } - - /// Construct a new `Type`. - pub fn new( - name: Option, - layout: Option, - kind: TypeKind, - is_const: bool, - ) -> Self { - Type { - name, - layout, - kind, - is_const, - } - } - - /// Which kind of type is this? - pub fn kind(&self) -> &TypeKind { - &self.kind - } - - /// Get a mutable reference to this type's kind. - pub fn kind_mut(&mut self) -> &mut TypeKind { - &mut self.kind - } - - /// Get this type's name. - pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|name| &**name) - } - - /// Is this a compound type? - pub fn is_comp(&self) -> bool { - match self.kind { - TypeKind::Comp(..) => true, - _ => false, - } - } - - /// Is this a union? - pub fn is_union(&self) -> bool { - match self.kind { - TypeKind::Comp(ref comp) => comp.is_union(), - _ => false, - } - } - - /// Is this type of kind `TypeKind::TypeParam`? - pub fn is_type_param(&self) -> bool { - match self.kind { - TypeKind::TypeParam => true, - _ => false, - } - } - - /// Is this a template instantiation type? - pub fn is_template_instantiation(&self) -> bool { - match self.kind { - TypeKind::TemplateInstantiation(..) => true, - _ => false, - } - } - - /// Is this a template alias type? - pub fn is_template_alias(&self) -> bool { - match self.kind { - TypeKind::TemplateAlias(..) => true, - _ => false, - } - } - - /// Is this a function type? - pub fn is_function(&self) -> bool { - match self.kind { - TypeKind::Function(..) => true, - _ => false, - } - } - - /// Is this an enum type? - pub fn is_enum(&self) -> bool { - match self.kind { - TypeKind::Enum(..) => true, - _ => false, - } - } - - /// Is this either a builtin or named type? - pub fn is_builtin_or_type_param(&self) -> bool { - match self.kind { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Function(..) | - TypeKind::Array(..) | - TypeKind::Reference(..) | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::TypeParam => true, - _ => false, - } - } - - /// Creates a new named type, with name `name`. - pub fn named(name: String) -> Self { - let name = if name.is_empty() { None } else { Some(name) }; - Self::new(name, None, TypeKind::TypeParam, false) - } - - /// Is this a floating point type? - pub fn is_float(&self) -> bool { - match self.kind { - TypeKind::Float(..) => true, - _ => false, - } - } - - /// Is this a boolean type? - pub fn is_bool(&self) -> bool { - match self.kind { - TypeKind::Int(IntKind::Bool) => true, - _ => false, - } - } - - /// Is this an integer type? - pub fn is_integer(&self) -> bool { - match self.kind { - TypeKind::Int(..) => true, - _ => false, - } - } - - /// Cast this type to an integer kind, or `None` if it is not an integer - /// type. - pub fn as_integer(&self) -> Option { - match self.kind { - TypeKind::Int(int_kind) => Some(int_kind), - _ => None, - } - } - - /// Is this a `const` qualified type? - pub fn is_const(&self) -> bool { - self.is_const - } - - /// Is this a reference to another type? - pub fn is_type_ref(&self) -> bool { - match self.kind { - TypeKind::ResolvedTypeRef(_) | - TypeKind::UnresolvedTypeRef(_, _, _) => true, - _ => false, - } - } - - /// Is this a incomplete array type? - pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option { - match self.kind { - TypeKind::Array(item, len) => { - if len == 0 { Some(item.into()) } else { None } - } - TypeKind::ResolvedTypeRef(inner) => { - ctx.resolve_type(inner).is_incomplete_array(ctx) - } - _ => None, - } - } - - /// What is the layout of this type? - pub fn layout(&self, ctx: &BindgenContext) -> Option { - self.layout.or_else(|| { - match self.kind { - TypeKind::Comp(ref ci) => ci.layout(ctx), - // FIXME(emilio): This is a hack for anonymous union templates. - // Use the actual pointer size! - TypeKind::Pointer(..) | - TypeKind::BlockPointer => { - Some(Layout::new( - ctx.target_pointer_size(), - ctx.target_pointer_size(), - )) - } - TypeKind::ResolvedTypeRef(inner) => { - ctx.resolve_type(inner).layout(ctx) - } - _ => None, - } - }) - } - - /// Whether this named type is an invalid C++ identifier. This is done to - /// avoid generating invalid code with some cases we can't handle, see: - /// - /// tests/headers/381-decltype-alias.hpp - pub fn is_invalid_type_param(&self) -> bool { - match self.kind { - TypeKind::TypeParam => { - let name = self.name().expect("Unnamed named type?"); - !clang::is_valid_identifier(&name) - } - _ => false, - } - } - - /// Takes `name`, and returns a suitable identifier representation for it. - fn sanitize_name<'a>(name: &'a str) -> Cow<'a, str> { - if clang::is_valid_identifier(name) { - return Cow::Borrowed(name); - } - - let name = name.replace(|c| c == ' ' || c == ':' || c == '.', "_"); - Cow::Owned(name) - } - - /// Get this type's santizied name. - pub fn sanitized_name<'a>( - &'a self, - ctx: &BindgenContext, - ) -> Option> { - let name_info = match *self.kind() { - TypeKind::Pointer(inner) => Some((inner.into(), Cow::Borrowed("ptr"))), - TypeKind::Reference(inner) => Some((inner.into(), Cow::Borrowed("ref"))), - TypeKind::Array(inner, length) => { - Some((inner, format!("array{}", length).into())) - } - _ => None, - }; - if let Some((inner, prefix)) = name_info { - ctx.resolve_item(inner) - .expect_type() - .sanitized_name(ctx) - .map(|name| format!("{}_{}", prefix, name).into()) - } else { - self.name().map(Self::sanitize_name) - } - } - - /// See safe_canonical_type. - pub fn canonical_type<'tr>( - &'tr self, - ctx: &'tr BindgenContext, - ) -> &'tr Type { - self.safe_canonical_type(ctx).expect( - "Should have been resolved after parsing!", - ) - } - - /// Returns the canonical type of this type, that is, the "inner type". - /// - /// For example, for a `typedef`, the canonical type would be the - /// `typedef`ed type, for a template instantiation, would be the template - /// its specializing, and so on. Return None if the type is unresolved. - pub fn safe_canonical_type<'tr>( - &'tr self, - ctx: &'tr BindgenContext, - ) -> Option<&'tr Type> { - match self.kind { - TypeKind::TypeParam | - TypeKind::Array(..) | - TypeKind::Comp(..) | - TypeKind::Opaque | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::BlockPointer | - TypeKind::Pointer(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::ObjCInterface(..) => Some(self), - - TypeKind::ResolvedTypeRef(inner) | - TypeKind::Alias(inner) | - TypeKind::TemplateAlias(inner, _) => { - ctx.resolve_type(inner).safe_canonical_type(ctx) - } - TypeKind::TemplateInstantiation(ref inst) => { - ctx.resolve_type(inst.template_definition()) - .safe_canonical_type(ctx) - } - - TypeKind::UnresolvedTypeRef(..) => None, - } - } - - /// There are some types we don't want to stop at when finding an opaque - /// item, so we can arrive to the proper item that needs to be generated. - pub fn should_be_traced_unconditionally(&self) -> bool { - match self.kind { - TypeKind::Comp(..) | - TypeKind::Function(..) | - TypeKind::Pointer(..) | - TypeKind::Array(..) | - TypeKind::Reference(..) | - TypeKind::TemplateInstantiation(..) | - TypeKind::ResolvedTypeRef(..) => true, - _ => false, - } - } -} - -impl IsOpaque for Type { - type Extra = Item; - - fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { - match self.kind { - TypeKind::Opaque => true, - TypeKind::TemplateInstantiation(ref inst) => { - inst.is_opaque(ctx, item) - } - TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &self.layout), - TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()), - _ => false, - } - } -} - -impl AsTemplateParam for Type { - type Extra = Item; - - fn as_template_param( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> Option { - self.kind.as_template_param(ctx, item) - } -} - -impl AsTemplateParam for TypeKind { - type Extra = Item; - - fn as_template_param( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> Option { - match *self { - TypeKind::TypeParam => Some(item.id().expect_type_id(ctx)), - TypeKind::ResolvedTypeRef(id) => id.as_template_param(ctx, &()), - _ => None, - } - } -} - -impl DotAttributes for Type { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - if let Some(ref layout) = self.layout { - writeln!( - out, - "size{} - align{}", - layout.size, - layout.align - )?; - if layout.packed { - writeln!(out, "packedtrue")?; - } - } - - if self.is_const { - writeln!(out, "consttrue")?; - } - - self.kind.dot_attributes(ctx, out) - } -} - -impl DotAttributes for TypeKind { - fn dot_attributes( - &self, - ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - writeln!(out, "type kind{}", self.kind_name())?; - - if let TypeKind::Comp(ref comp) = *self { - comp.dot_attributes(ctx, out)?; - } - - Ok(()) - } -} - -impl TypeKind { - fn kind_name(&self) -> &'static str { - match *self { - TypeKind::Void => "Void", - TypeKind::NullPtr => "NullPtr", - TypeKind::Comp(..) => "Comp", - TypeKind::Opaque => "Opaque", - TypeKind::Int(..) => "Int", - TypeKind::Float(..) => "Float", - TypeKind::Complex(..) => "Complex", - TypeKind::Alias(..) => "Alias", - TypeKind::TemplateAlias(..) => "TemplateAlias", - TypeKind::Array(..) => "Array", - TypeKind::Function(..) => "Function", - TypeKind::Enum(..) => "Enum", - TypeKind::Pointer(..) => "Pointer", - TypeKind::BlockPointer => "BlockPointer", - TypeKind::Reference(..) => "Reference", - TypeKind::TemplateInstantiation(..) => "TemplateInstantiation", - TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef", - TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef", - TypeKind::TypeParam => "TypeParam", - TypeKind::ObjCInterface(..) => "ObjCInterface", - TypeKind::ObjCId => "ObjCId", - TypeKind::ObjCSel => "ObjCSel", - } - } -} - -#[test] -fn is_invalid_type_param_valid() { - let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false); - assert!(!ty.is_invalid_type_param()) -} - -#[test] -fn is_invalid_type_param_valid_underscore_and_numbers() { - let ty = Type::new( - Some("_foo123456789_".into()), - None, - TypeKind::TypeParam, - false, - ); - assert!(!ty.is_invalid_type_param()) -} - -#[test] -fn is_invalid_type_param_valid_unnamed_kind() { - let ty = Type::new(Some("foo".into()), None, TypeKind::Void, false); - assert!(!ty.is_invalid_type_param()) -} - -#[test] -fn is_invalid_type_param_invalid_start() { - let ty = Type::new(Some("1foo".into()), None, TypeKind::TypeParam, false); - assert!(ty.is_invalid_type_param()) -} - -#[test] -fn is_invalid_type_param_invalid_remaing() { - let ty = Type::new(Some("foo-".into()), None, TypeKind::TypeParam, false); - assert!(ty.is_invalid_type_param()) -} - -#[test] -#[should_panic] -fn is_invalid_type_param_unnamed() { - let ty = Type::new(None, None, TypeKind::TypeParam, false); - assert!(ty.is_invalid_type_param()) -} - -#[test] -fn is_invalid_type_param_empty_name() { - let ty = Type::new(Some("".into()), None, TypeKind::TypeParam, false); - assert!(ty.is_invalid_type_param()) -} - -impl TemplateParameters for Type { - fn self_template_params( - &self, - ctx: &BindgenContext, - ) -> Option> { - self.kind.self_template_params(ctx) - } -} - -impl TemplateParameters for TypeKind { - fn self_template_params( - &self, - ctx: &BindgenContext, - ) -> Option> { - match *self { - TypeKind::ResolvedTypeRef(id) => { - ctx.resolve_type(id).self_template_params(ctx) - } - TypeKind::Comp(ref comp) => comp.self_template_params(ctx), - TypeKind::TemplateAlias(_, ref args) => Some(args.clone()), - - TypeKind::Opaque | - TypeKind::TemplateInstantiation(..) | - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(_) | - TypeKind::Float(_) | - TypeKind::Complex(_) | - TypeKind::Array(..) | - TypeKind::Function(_) | - TypeKind::Enum(_) | - TypeKind::Pointer(_) | - TypeKind::BlockPointer | - TypeKind::Reference(_) | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::TypeParam | - TypeKind::Alias(_) | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::ObjCInterface(_) => None, - } - } -} - -/// The kind of float this type represents. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FloatKind { - /// A `float`. - Float, - /// A `double`. - Double, - /// A `long double`. - LongDouble, - /// A `__float128`. - Float128, -} - -/// The different kinds of types that we can parse. -#[derive(Debug)] -pub enum TypeKind { - /// The void type. - Void, - - /// The `nullptr_t` type. - NullPtr, - - /// A compound type, that is, a class, struct, or union. - Comp(CompInfo), - - /// An opaque type that we just don't understand. All usage of this shoulf - /// result in an opaque blob of bytes generated from the containing type's - /// layout. - Opaque, - - /// An integer type, of a given kind. `bool` and `char` are also considered - /// integers. - Int(IntKind), - - /// A floating point type. - Float(FloatKind), - - /// A complex floating point type. - Complex(FloatKind), - - /// A type alias, with a name, that points to another type. - Alias(TypeId), - - /// A templated alias, pointing to an inner type, just as `Alias`, but with - /// template parameters. - TemplateAlias(TypeId, Vec), - - /// An array of a type and a length. - Array(TypeId, usize), - - /// A function type, with a given signature. - Function(FunctionSig), - - /// An `enum` type. - Enum(Enum), - - /// A pointer to a type. The bool field represents whether it's const or - /// not. - Pointer(TypeId), - - /// A pointer to an Apple block. - BlockPointer, - - /// A reference to a type, as in: int& foo(). - Reference(TypeId), - - /// An instantiation of an abstract template definition with a set of - /// concrete template arguments. - TemplateInstantiation(TemplateInstantiation), - - /// A reference to a yet-to-resolve type. This stores the clang cursor - /// itself, and postpones its resolution. - /// - /// These are gone in a phase after parsing where these are mapped to - /// already known types, and are converted to ResolvedTypeRef. - /// - /// see tests/headers/typeref.hpp to see somewhere where this is a problem. - UnresolvedTypeRef( - clang::Type, - clang::Cursor, - /* parent_id */ - Option - ), - - /// An indirection to another type. - /// - /// These are generated after we resolve a forward declaration, or when we - /// replace one type with another. - ResolvedTypeRef(TypeId), - - /// A named type, that is, a template parameter. - TypeParam, - - /// Objective C interface. Always referenced through a pointer - ObjCInterface(ObjCInterface), - - /// Objective C 'id' type, points to any object - ObjCId, - - /// Objective C selector type - ObjCSel, -} - -impl Type { - /// This is another of the nasty methods. This one is the one that takes - /// care of the core logic of converting a clang type to a `Type`. - /// - /// It's sort of nasty and full of special-casing, but hopefully the - /// comments in every special case justify why they're there. - pub fn from_clang_ty( - potential_id: ItemId, - ty: &clang::Type, - location: Cursor, - parent_id: Option, - ctx: &mut BindgenContext, - ) -> Result, ParseError> { - use clang_sys::*; - { - let already_resolved = ctx.builtin_or_resolved_ty( - potential_id, - parent_id, - ty, - Some(location), - ); - if let Some(ty) = already_resolved { - debug!("{:?} already resolved: {:?}", ty, location); - return Ok(ParseResult::AlreadyResolved(ty.into())); - } - } - - let layout = ty.fallible_layout().ok(); - let cursor = ty.declaration(); - let mut name = cursor.spelling(); - - debug!( - "from_clang_ty: {:?}, ty: {:?}, loc: {:?}", - potential_id, - ty, - location - ); - debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types()); - - let canonical_ty = ty.canonical_type(); - - // Parse objc protocols as if they were interfaces - let mut ty_kind = ty.kind(); - match location.kind() { - CXCursor_ObjCProtocolDecl | - CXCursor_ObjCCategoryDecl => ty_kind = CXType_ObjCInterface, - _ => {} - } - - // Objective C template type parameter - // FIXME: This is probably wrong, we are attempting to find the - // objc template params, which seem to manifest as a typedef. - // We are rewriting them as id to suppress multiple conflicting - // typedefs at root level - if ty_kind == CXType_Typedef { - let is_template_type_param = ty.declaration().kind() == - CXCursor_TemplateTypeParameter; - let is_canonical_objcpointer = canonical_ty.kind() == - CXType_ObjCObjectPointer; - - // We have found a template type for objc interface - if is_canonical_objcpointer && is_template_type_param { - // Objective-C generics are just ids with fancy name. - // To keep it simple, just name them ids - name = "id".to_owned(); - } - - } - - if location.kind() == CXCursor_ClassTemplatePartialSpecialization { - // Sorry! (Not sorry) - warn!( - "Found a partial template specialization; bindgen does not \ - support partial template specialization! Constructing \ - opaque type instead." - ); - return Ok( - ParseResult::New(Opaque::from_clang_ty(&canonical_ty), None), - ); - } - - let kind = if location.kind() == CXCursor_TemplateRef || - (ty.template_args().is_some() && ty_kind != CXType_Typedef) - { - // This is a template instantiation. - match TemplateInstantiation::from_ty(&ty, ctx) { - Some(inst) => TypeKind::TemplateInstantiation(inst), - None => TypeKind::Opaque, - } - } else { - match ty_kind { - CXType_Unexposed if *ty != canonical_ty && - canonical_ty.kind() != CXType_Invalid && - ty.ret_type().is_none() && - // Sometime clang desugars some types more than - // what we need, specially with function - // pointers. - // - // We should also try the solution of inverting - // those checks instead of doing this, that is, - // something like: - // - // CXType_Unexposed if ty.ret_type().is_some() - // => { ... } - // - // etc. - !canonical_ty.spelling().contains("type-parameter") => { - debug!("Looking for canonical type: {:?}", canonical_ty); - return Self::from_clang_ty(potential_id, - &canonical_ty, - location, - parent_id, - ctx); - } - CXType_Unexposed | CXType_Invalid => { - // For some reason Clang doesn't give us any hint in some - // situations where we should generate a function pointer (see - // tests/headers/func_ptr_in_struct.h), so we do a guess here - // trying to see if it has a valid return type. - if ty.ret_type().is_some() { - let signature = - FunctionSig::from_ty(ty, &location, ctx)?; - TypeKind::Function(signature) - // Same here, with template specialisations we can safely - // assume this is a Comp(..) - } else if ty.is_fully_instantiated_template() { - debug!( - "Template specialization: {:?}, {:?} {:?}", - ty, - location, - canonical_ty - ); - let complex = CompInfo::from_ty( - potential_id, - ty, - Some(location), - ctx, - ).expect("C'mon"); - TypeKind::Comp(complex) - } else { - match location.kind() { - CXCursor_CXXBaseSpecifier | - CXCursor_ClassTemplate => { - if location.kind() == - CXCursor_CXXBaseSpecifier - { - // In the case we're parsing a base specifier - // inside an unexposed or invalid type, it means - // that we're parsing one of two things: - // - // * A template parameter. - // * A complex class that isn't exposed. - // - // This means, unfortunately, that there's no - // good way to differentiate between them. - // - // Probably we could try to look at the - // declaration and complicate more this logic, - // but we'll keep it simple... if it's a valid - // C++ identifier, we'll consider it as a - // template parameter. - // - // This is because: - // - // * We expect every other base that is a - // proper identifier (that is, a simple - // struct/union declaration), to be exposed, - // so this path can't be reached in that - // case. - // - // * Quite conveniently, complex base - // specifiers preserve their full names (that - // is: Foo instead of Foo). We can take - // advantage of this. - // - // If we find some edge case where this doesn't - // work (which I guess is unlikely, see the - // different test cases[1][2][3][4]), we'd need - // to find more creative ways of differentiating - // these two cases. - // - // [1]: inherit_named.hpp - // [2]: forward-inherit-struct-with-fields.hpp - // [3]: forward-inherit-struct.hpp - // [4]: inherit-namespaced.hpp - if location.spelling().chars().all(|c| { - c.is_alphanumeric() || c == '_' - }) - { - return Err(ParseError::Recurse); - } - } else { - name = location.spelling(); - } - - let complex = CompInfo::from_ty( - potential_id, - ty, - Some(location), - ctx, - ); - match complex { - Ok(complex) => TypeKind::Comp(complex), - Err(_) => { - warn!( - "Could not create complex type \ - from class template or base \ - specifier, using opaque blob" - ); - let opaque = Opaque::from_clang_ty(ty); - return Ok( - ParseResult::New(opaque, None), - ); - } - } - } - CXCursor_TypeAliasTemplateDecl => { - debug!("TypeAliasTemplateDecl"); - - // We need to manually unwind this one. - let mut inner = Err(ParseError::Continue); - let mut args = vec![]; - - location.visit(|cur| { - match cur.kind() { - CXCursor_TypeAliasDecl => { - let current = cur.cur_type(); - - debug_assert_eq!( - current.kind(), - CXType_Typedef - ); - - name = current.spelling(); - - let inner_ty = cur.typedef_type() - .expect("Not valid Type?"); - inner = Ok(Item::from_ty_or_ref( - inner_ty, - cur, - Some(potential_id), - ctx, - )); - } - CXCursor_TemplateTypeParameter => { - let param = - Item::type_param(None, - cur, - ctx) - .expect("Item::type_param shouldn't \ - ever fail if we are looking \ - at a TemplateTypeParameter"); - args.push(param); - } - _ => {} - } - CXChildVisit_Continue - }); - - let inner_type = match inner { - Ok(inner) => inner, - Err(..) => { - error!( - "Failed to parse template alias \ - {:?}", - location - ); - return Err(ParseError::Continue); - } - }; - - TypeKind::TemplateAlias(inner_type, args) - } - CXCursor_TemplateRef => { - let referenced = location.referenced().unwrap(); - let referenced_ty = referenced.cur_type(); - - debug!( - "TemplateRef: location = {:?}; referenced = \ - {:?}; referenced_ty = {:?}", - location, - referenced, - referenced_ty - ); - - return Self::from_clang_ty( - potential_id, - &referenced_ty, - referenced, - parent_id, - ctx, - ); - } - CXCursor_TypeRef => { - let referenced = location.referenced().unwrap(); - let referenced_ty = referenced.cur_type(); - let declaration = referenced_ty.declaration(); - - debug!( - "TypeRef: location = {:?}; referenced = \ - {:?}; referenced_ty = {:?}", - location, - referenced, - referenced_ty - ); - - let id = Item::from_ty_or_ref_with_id( - potential_id, - referenced_ty, - declaration, - parent_id, - ctx, - ); - return Ok(ParseResult::AlreadyResolved(id.into())); - } - CXCursor_NamespaceRef => { - return Err(ParseError::Continue); - } - _ => { - if ty.kind() == CXType_Unexposed { - warn!( - "Unexposed type {:?}, recursing inside, \ - loc: {:?}", - ty, - location - ); - return Err(ParseError::Recurse); - } - - warn!("invalid type {:?}", ty); - return Err(ParseError::Continue); - } - } - } - } - CXType_Auto => { - if canonical_ty == *ty { - debug!("Couldn't find deduced type: {:?}", ty); - return Err(ParseError::Continue); - } - - return Self::from_clang_ty( - potential_id, - &canonical_ty, - location, - parent_id, - ctx, - ); - } - // NOTE: We don't resolve pointers eagerly because the pointee type - // might not have been parsed, and if it contains templates or - // something else we might get confused, see the comment inside - // TypeRef. - // - // We might need to, though, if the context is already in the - // process of resolving them. - CXType_ObjCObjectPointer | - CXType_MemberPointer | - CXType_Pointer => { - // Fun fact: the canonical type of a pointer type may sometimes - // contain information we need but isn't present in the concrete - // type (yeah, I'm equally wat'd). - // - // Yet we still have trouble if we unconditionally trust the - // canonical type, like too-much desugaring (sigh). - // - // See tests/headers/call-conv-field.h for an example. - // - // Since for now the only identifier cause of breakage is the - // ABI for function pointers, and different ABI mixed with - // problematic stuff like that one is _extremely_ unlikely and - // can be bypassed via blacklisting, we do the check explicitly - // (as hacky as it is). - // - // Yet we should probably (somehow) get the best of both worlds, - // presumably special-casing function pointers as a whole, yet - // someone is going to need to care about typedef'd function - // pointers, etc, which isn't trivial given function pointers - // are mostly unexposed. I don't have the time for it right now. - let mut pointee = ty.pointee_type().unwrap(); - let canonical_pointee = - canonical_ty.pointee_type().unwrap(); - if pointee.call_conv() != canonical_pointee.call_conv() { - pointee = canonical_pointee; - } - let inner = - Item::from_ty_or_ref(pointee, location, None, ctx); - TypeKind::Pointer(inner) - } - CXType_BlockPointer => TypeKind::BlockPointer, - // XXX: RValueReference is most likely wrong, but I don't think we - // can even add bindings for that, so huh. - CXType_RValueReference | - CXType_LValueReference => { - let inner = Item::from_ty_or_ref( - ty.pointee_type().unwrap(), - location, - None, - ctx, - ); - TypeKind::Reference(inner) - } - // XXX DependentSizedArray is wrong - CXType_VariableArray | - CXType_DependentSizedArray => { - let inner = Item::from_ty( - ty.elem_type().as_ref().unwrap(), - location, - None, - ctx, - ).expect("Not able to resolve array element?"); - TypeKind::Pointer(inner) - } - CXType_IncompleteArray => { - let inner = Item::from_ty( - ty.elem_type().as_ref().unwrap(), - location, - None, - ctx, - ).expect("Not able to resolve array element?"); - TypeKind::Array(inner, 0) - } - CXType_FunctionNoProto | - CXType_FunctionProto => { - let signature = - FunctionSig::from_ty(ty, &location, ctx)?; - TypeKind::Function(signature) - } - CXType_Typedef => { - let inner = cursor.typedef_type().expect("Not valid Type?"); - let inner = - Item::from_ty_or_ref(inner, location, None, ctx); - TypeKind::Alias(inner) - } - CXType_Enum => { - let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?"); - - if name.is_empty() { - let pretty_name = ty.spelling(); - if clang::is_valid_identifier(&pretty_name) { - name = pretty_name; - } - } - - TypeKind::Enum(enum_) - } - CXType_Record => { - let complex = CompInfo::from_ty( - potential_id, - ty, - Some(location), - ctx, - ).expect("Not a complex type?"); - - if name.is_empty() { - // The pretty-printed name may contain typedefed name, - // but may also be "struct (anonymous at .h:1)" - let pretty_name = ty.spelling(); - if clang::is_valid_identifier(&pretty_name) { - name = pretty_name; - } - } - - TypeKind::Comp(complex) - } - // FIXME: We stub vectors as arrays since in 99% of the cases the - // layout is going to be correct, and there's no way we can generate - // vector types properly in Rust for now. - // - // That being said, that should be fixed eventually. - CXType_Vector | - CXType_ConstantArray => { - let inner = Item::from_ty( - ty.elem_type().as_ref().unwrap(), - location, - None, - ctx, - ).expect("Not able to resolve array element?"); - TypeKind::Array(inner, ty.num_elements().unwrap()) - } - CXType_Elaborated => { - return Self::from_clang_ty( - potential_id, - &ty.named(), - location, - parent_id, - ctx, - ); - } - CXType_ObjCId => TypeKind::ObjCId, - CXType_ObjCSel => TypeKind::ObjCSel, - CXType_ObjCClass | - CXType_ObjCInterface => { - let interface = ObjCInterface::from_ty(&location, ctx) - .expect("Not a valid objc interface?"); - name = interface.rust_name(); - TypeKind::ObjCInterface(interface) - } - _ => { - error!( - "unsupported type: kind = {:?}; ty = {:?}; at {:?}", - ty.kind(), - ty, - location - ); - return Err(ParseError::Continue); - } - } - }; - - let name = if name.is_empty() { None } else { Some(name) }; - let is_const = ty.is_const(); - - let ty = Type::new(name, layout, kind, is_const); - // TODO: maybe declaration.canonical()? - Ok(ParseResult::New(ty, Some(cursor.canonical()))) - } -} - -impl Trace for Type { - type Extra = Item; - - fn trace(&self, context: &BindgenContext, tracer: &mut T, item: &Item) - where - T: Tracer, - { - match *self.kind() { - TypeKind::Pointer(inner) | - TypeKind::Reference(inner) | - TypeKind::Array(inner, _) | - TypeKind::Alias(inner) | - TypeKind::ResolvedTypeRef(inner) => { - tracer.visit_kind(inner.into(), EdgeKind::TypeReference); - } - TypeKind::TemplateAlias(inner, ref template_params) => { - tracer.visit_kind(inner.into(), EdgeKind::TypeReference); - for param in template_params { - tracer.visit_kind( - param.into(), - EdgeKind::TemplateParameterDefinition, - ); - } - } - TypeKind::TemplateInstantiation(ref inst) => { - inst.trace(context, tracer, &()); - } - TypeKind::Comp(ref ci) => ci.trace(context, tracer, item), - TypeKind::Function(ref sig) => sig.trace(context, tracer, &()), - TypeKind::Enum(ref en) => { - if let Some(repr) = en.repr() { - tracer.visit(repr.into()); - } - } - TypeKind::UnresolvedTypeRef(_, _, Some(id)) => { - tracer.visit(id); - } - - TypeKind::ObjCInterface(ref interface) => { - interface.trace(context, tracer, &()); - } - - // None of these variants have edges to other items and types. - TypeKind::Opaque | - TypeKind::UnresolvedTypeRef(_, _, None) | - TypeKind::TypeParam | - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(_) | - TypeKind::Float(_) | - TypeKind::Complex(_) | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::BlockPointer => {} - } - } -} diff --git a/src/ir/var.rs b/src/ir/var.rs deleted file mode 100644 index 25ac56d2cd..0000000000 --- a/src/ir/var.rs +++ /dev/null @@ -1,372 +0,0 @@ -//! Intermediate representation of variables. - -use callbacks::MacroParsingBehavior; -use super::context::{BindgenContext, TypeId}; -use super::dot::DotAttributes; -use super::function::cursor_mangling; -use super::int::IntKind; -use super::item::Item; -use super::ty::{FloatKind, TypeKind}; -use cexpr; -use clang; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use std::io; -use std::num::Wrapping; - -/// The type for a constant variable. -#[derive(Debug)] -pub enum VarType { - /// A boolean. - Bool(bool), - /// An integer. - Int(i64), - /// A floating point number. - Float(f64), - /// A character. - Char(u8), - /// A string, not necessarily well-formed utf-8. - String(Vec), -} - -/// A `Var` is our intermediate representation of a variable. -#[derive(Debug)] -pub struct Var { - /// The name of the variable. - name: String, - /// The mangled name of the variable. - mangled_name: Option, - /// The type of the variable. - ty: TypeId, - /// The value of the variable, that needs to be suitable for `ty`. - val: Option, - /// Whether this variable is const. - is_const: bool, -} - -impl Var { - /// Construct a new `Var`. - pub fn new( - name: String, - mangled_name: Option, - ty: TypeId, - val: Option, - is_const: bool, - ) -> Var { - assert!(!name.is_empty()); - Var { - name, - mangled_name, - ty, - val, - is_const, - } - } - - /// Is this variable `const` qualified? - pub fn is_const(&self) -> bool { - self.is_const - } - - /// The value of this constant variable, if any. - pub fn val(&self) -> Option<&VarType> { - self.val.as_ref() - } - - /// Get this variable's type. - pub fn ty(&self) -> TypeId { - self.ty - } - - /// Get this variable's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this variable's mangled name. - pub fn mangled_name(&self) -> Option<&str> { - self.mangled_name.as_ref().map(|n| &**n) - } -} - -impl DotAttributes for Var { - fn dot_attributes( - &self, - _ctx: &BindgenContext, - out: &mut W, - ) -> io::Result<()> - where - W: io::Write, - { - if self.is_const { - writeln!(out, "consttrue")?; - } - - if let Some(ref mangled) = self.mangled_name { - writeln!( - out, - "mangled name{}", - mangled - )?; - } - - Ok(()) - } -} - -// TODO(emilio): we could make this more (or less) granular, I guess. -fn default_macro_constant_type(value: i64) -> IntKind { - if value < 0 { - if value < i32::min_value() as i64 { - IntKind::I64 - } else { - IntKind::I32 - } - } else if value > u32::max_value() as i64 { - IntKind::U64 - } else { - IntKind::U32 - } -} - -impl ClangSubItemParser for Var { - fn parse( - cursor: clang::Cursor, - ctx: &mut BindgenContext, - ) -> Result, ParseError> { - use clang_sys::*; - use cexpr::expr::EvalResult; - use cexpr::literal::CChar; - match cursor.kind() { - CXCursor_MacroDefinition => { - if let Some(callbacks) = ctx.parse_callbacks() { - match callbacks.will_parse_macro(&cursor.spelling()) { - MacroParsingBehavior::Ignore => { - return Err(ParseError::Continue); - } - MacroParsingBehavior::Default => {} - } - } - - let value = parse_macro(ctx, &cursor); - - let (id, value) = match value { - Some(v) => v, - None => return Err(ParseError::Continue), - }; - - assert!(!id.is_empty(), "Empty macro name?"); - - let previously_defined = ctx.parsed_macro(&id); - - // NB: It's important to "note" the macro even if the result is - // not an integer, otherwise we might loose other kind of - // derived macros. - ctx.note_parsed_macro(id.clone(), value.clone()); - - if previously_defined { - let name = String::from_utf8(id).unwrap(); - warn!("Duplicated macro definition: {}", name); - return Err(ParseError::Continue); - } - - // NOTE: Unwrapping, here and above, is safe, because the - // identifier of a token comes straight from clang, and we - // enforce utf8 there, so we should have already panicked at - // this point. - let name = String::from_utf8(id).unwrap(); - let (type_kind, val) = match value { - EvalResult::Invalid => return Err(ParseError::Continue), - EvalResult::Float(f) => { - (TypeKind::Float(FloatKind::Double), VarType::Float(f)) - } - EvalResult::Char(c) => { - let c = match c { - CChar::Char(c) => { - assert_eq!(c.len_utf8(), 1); - c as u8 - } - CChar::Raw(c) => { - assert!(c <= ::std::u8::MAX as u64); - c as u8 - } - }; - - (TypeKind::Int(IntKind::U8), VarType::Char(c)) - } - EvalResult::Str(val) => { - let char_ty = Item::builtin_type( - TypeKind::Int(IntKind::U8), - true, - ctx, - ); - (TypeKind::Pointer(char_ty), VarType::String(val)) - } - EvalResult::Int(Wrapping(value)) => { - let kind = ctx.parse_callbacks() - .and_then(|c| c.int_macro(&name, value)) - .unwrap_or_else(|| default_macro_constant_type(value)); - - (TypeKind::Int(kind), VarType::Int(value)) - } - }; - - let ty = Item::builtin_type(type_kind, true, ctx); - - Ok(ParseResult::New( - Var::new(name, None, ty, Some(val), true), - Some(cursor), - )) - } - CXCursor_VarDecl => { - let name = cursor.spelling(); - if name.is_empty() { - warn!("Empty constant name?"); - return Err(ParseError::Continue); - } - - let ty = cursor.cur_type(); - - // XXX this is redundant, remove! - let is_const = ty.is_const(); - - let ty = match Item::from_ty(&ty, cursor, None, ctx) { - Ok(ty) => ty, - Err(e) => { - assert_eq!( - ty.kind(), - CXType_Auto, - "Couldn't resolve constant type, and it \ - wasn't an nondeductible auto type!" - ); - return Err(e); - } - }; - - // Note: Ty might not be totally resolved yet, see - // tests/headers/inner_const.hpp - // - // That's fine because in that case we know it's not a literal. - let canonical_ty = ctx.safe_resolve_type(ty).and_then(|t| { - t.safe_canonical_type(ctx) - }); - - let is_integer = canonical_ty.map_or(false, |t| t.is_integer()); - let is_float = canonical_ty.map_or(false, |t| t.is_float()); - - // TODO: We could handle `char` more gracefully. - // TODO: Strings, though the lookup is a bit more hard (we need - // to look at the canonical type of the pointee too, and check - // is char, u8, or i8 I guess). - let value = if is_integer { - let kind = match *canonical_ty.unwrap().kind() { - TypeKind::Int(kind) => kind, - _ => unreachable!(), - }; - - let mut val = cursor - .evaluate() - .and_then(|v| v.as_int()) - .map(|val| val as i64); - if val.is_none() || !kind.signedness_matches(val.unwrap()) { - let tu = ctx.translation_unit(); - val = get_integer_literal_from_cursor(&cursor, tu); - } - - val.map(|val| if kind == IntKind::Bool { - VarType::Bool(val != 0) - } else { - VarType::Int(val) - }) - } else if is_float { - cursor.evaluate().and_then(|v| v.as_double()).map( - VarType::Float, - ) - } else { - cursor.evaluate().and_then(|v| v.as_literal_string()).map( - VarType::String, - ) - }; - - let mangling = cursor_mangling(ctx, &cursor); - let var = Var::new(name, mangling, ty, value, is_const); - - Ok(ParseResult::New(var, Some(cursor))) - } - _ => { - /* TODO */ - Err(ParseError::Continue) - } - } - } -} - -/// Try and parse a macro using all the macros parsed until now. -fn parse_macro( - ctx: &BindgenContext, - cursor: &clang::Cursor, -) -> Option<(Vec, cexpr::expr::EvalResult)> { - use cexpr::{expr, nom}; - - let mut cexpr_tokens = cursor.cexpr_tokens()?; - - let parser = expr::IdentifierParser::new(ctx.parsed_macros()); - - match parser.macro_definition(&cexpr_tokens) { - nom::IResult::Done(_, (id, val)) => { - return Some((id.into(), val)); - } - _ => {} - } - - // Try without the last token, to workaround a libclang bug in versions - // previous to 4.0. - // - // See: - // https://bugs.llvm.org//show_bug.cgi?id=9069 - // https://reviews.llvm.org/D26446 - cexpr_tokens.pop()?; - - match parser.macro_definition(&cexpr_tokens) { - nom::IResult::Done(_, (id, val)) => Some((id.into(), val)), - _ => None, - } -} - -fn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option { - use cexpr::{expr, nom}; - use cexpr::expr::EvalResult; - - let cexpr_tokens = cursor.cexpr_tokens()?; - - // TODO(emilio): We can try to parse other kinds of literals. - match expr::expr(&cexpr_tokens) { - nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val), - _ => None, - } -} - -fn get_integer_literal_from_cursor( - cursor: &clang::Cursor, - unit: &clang::TranslationUnit, -) -> Option { - use clang_sys::*; - let mut value = None; - cursor.visit(|c| { - match c.kind() { - CXCursor_IntegerLiteral | - CXCursor_UnaryOperator => { - value = parse_int_literal_tokens(&c); - } - CXCursor_UnexposedExpr => { - value = get_integer_literal_from_cursor(&c, unit); - } - _ => (), - } - if value.is_some() { - CXChildVisit_Break - } else { - CXChildVisit_Continue - } - }); - value -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index c715b9c2fb..0000000000 --- a/src/lib.rs +++ /dev/null @@ -1,1906 +0,0 @@ -//! Generate Rust bindings for C and C++ libraries. -//! -//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++ -//! functions and use types defined in the header. -//! -//! See the [`Builder`](./struct.Builder.html) struct for usage. -//! -//! See the [Users Guide](https://rust-lang-nursery.github.io/rust-bindgen/) for -//! additional documentation. -#![deny(missing_docs)] -#![deny(warnings)] -#![deny(unused_extern_crates)] -// To avoid rather annoying warnings when matching with CXCursor_xxx as a -// constant. -#![allow(non_upper_case_globals)] -// `quote!` nests quite deeply. -#![recursion_limit="128"] - -extern crate cexpr; -#[macro_use] -#[allow(unused_extern_crates)] -extern crate cfg_if; -extern crate clang_sys; -#[macro_use] -extern crate lazy_static; -extern crate peeking_take_while; -#[macro_use] -extern crate quote; -extern crate proc_macro2; -extern crate regex; -extern crate which; - -#[cfg(feature = "logging")] -#[macro_use] -extern crate log; - -#[cfg(not(feature = "logging"))] -#[macro_use] -mod log_stubs; - -#[macro_use] -mod extra_assertions; - -// A macro to declare an internal module for which we *must* provide -// documentation for. If we are building with the "testing_only_docs" feature, -// then the module is declared public, and our `#![deny(missing_docs)]` pragma -// applies to it. This feature is used in CI, so we won't let anything slip by -// undocumented. Normal builds, however, will leave the module private, so that -// we don't expose internals to library consumers. -macro_rules! doc_mod { - ($m:ident, $doc_mod_name:ident) => { - cfg_if! { - if #[cfg(feature = "testing_only_docs")] { - pub mod $doc_mod_name { - //! Autogenerated documentation module. - pub use super::$m::*; - } - } else { - } - } - }; -} - -mod clang; -mod codegen; -mod features; -mod ir; -mod parse; -mod regex_set; -mod time; - -pub mod callbacks; - -doc_mod!(clang, clang_docs); -doc_mod!(features, features_docs); -doc_mod!(ir, ir_docs); -doc_mod!(parse, parse_docs); -doc_mod!(regex_set, regex_set_docs); - -pub use features::{LATEST_STABLE_RUST, RUST_TARGET_STRINGS, RustTarget}; -use features::RustFeatures; -use ir::context::{BindgenContext, ItemId}; -use ir::item::Item; -use parse::{ClangItemParser, ParseError}; -use regex_set::RegexSet; - -use std::borrow::Cow; -use std::fs::{File, OpenOptions}; -use std::io::{self, Write}; -use std::iter; -use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; -use std::sync::Arc; - -/// A type used to indicate which kind of items do we have to generate. -/// -/// TODO(emilio): Use `bitflags!` -#[derive(Debug, Clone)] -pub struct CodegenConfig { - /// Whether to generate functions. - pub functions: bool, - /// Whether to generate types. - pub types: bool, - /// Whether to generate constants. - pub vars: bool, - /// Whether to generate methods. - pub methods: bool, - /// Whether to generate constructors. - pub constructors: bool, - /// Whether to generate destructors. - pub destructors: bool, -} - -impl CodegenConfig { - /// Generate all kinds of items. - pub fn all() -> Self { - CodegenConfig { - functions: true, - types: true, - vars: true, - methods: true, - constructors: true, - destructors: true, - } - } - - /// Generate nothing. - pub fn nothing() -> Self { - CodegenConfig { - functions: false, - types: false, - vars: false, - methods: false, - constructors: false, - destructors: false, - } - } -} - -impl Default for CodegenConfig { - fn default() -> Self { - CodegenConfig::all() - } -} - -/// Configure and generate Rust bindings for a C/C++ header. -/// -/// This is the main entry point to the library. -/// -/// ```ignore -/// use bindgen::builder; -/// -/// // Configure and generate bindings. -/// let bindings = builder().header("path/to/input/header") -/// .whitelisted_type("SomeCoolClass") -/// .whitelisted_function("do_some_cool_thing") -/// .generate()?; -/// -/// // Write the generated bindings to an output file. -/// bindings.write_to_file("path/to/output.rs")?; -/// ``` -/// -/// # Enums -/// -/// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on -/// the pattern passed to several methods: -/// -/// 1. [`constified_enum_module()`](#method.constified_enum_module) -/// 2. [`bitfield_enum()`](#method.bitfield_enum) -/// 3. [`rustified_enum()`](#method.rustified_enum) -/// -/// For each C enum, bindgen tries to match the pattern in the following order: -/// -/// 1. Constified enum module -/// 2. Bitfield enum -/// 3. Rustified enum -/// -/// If none of the above patterns match, then bindgen will generate a set of Rust constants. -#[derive(Debug, Default)] -pub struct Builder { - options: BindgenOptions, - input_headers: Vec, - // Tuples of unsaved file contents of the form (name, contents). - input_header_contents: Vec<(String, String)>, -} - -/// Construct a new [`Builder`](./struct.Builder.html). -pub fn builder() -> Builder { - Default::default() -} - -impl Builder { - /// Generates the command line flags use for creating `Builder`. - pub fn command_line_flags(&self) -> Vec { - let mut output_vector: Vec = Vec::new(); - - if let Some(header) = self.input_headers.last().cloned() { - // Positional argument 'header' - output_vector.push(header); - } - - output_vector.push("--rust-target".into()); - output_vector.push(self.options.rust_target.into()); - - self.options - .bitfield_enums - .get_items() - .iter() - .map(|item| { - output_vector.push("--bitfield-enum".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .rustified_enums - .get_items() - .iter() - .map(|item| { - output_vector.push("--rustified-enum".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .constified_enum_modules - .get_items() - .iter() - .map(|item| { - output_vector.push("--constified-enum-module".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .blacklisted_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--blacklist-type".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - if !self.options.layout_tests { - output_vector.push("--no-layout-tests".into()); - } - - if self.options.impl_debug { - output_vector.push("--impl-debug".into()); - } - - if self.options.impl_partialeq { - output_vector.push("--impl-partialeq".into()); - } - - if !self.options.derive_copy { - output_vector.push("--no-derive-copy".into()); - } - - if !self.options.derive_debug { - output_vector.push("--no-derive-debug".into()); - } - - if !self.options.derive_default { - output_vector.push("--no-derive-default".into()); - } else { - output_vector.push("--with-derive-default".into()); - } - - if self.options.derive_hash { - output_vector.push("--with-derive-hash".into()); - } - - if self.options.derive_partialord { - output_vector.push("--with-derive-partialord".into()); - } - - if self.options.derive_ord { - output_vector.push("--with-derive-ord".into()); - } - - if self.options.derive_partialeq { - output_vector.push("--with-derive-partialeq".into()); - } - - if self.options.derive_eq { - output_vector.push("--with-derive-eq".into()); - } - - if self.options.time_phases { - output_vector.push("--time-phases".into()); - } - - if !self.options.generate_comments { - output_vector.push("--no-doc-comments".into()); - } - - if !self.options.whitelist_recursively { - output_vector.push("--no-recursive-whitelist".into()); - } - - if self.options.objc_extern_crate { - output_vector.push("--objc-extern-crate".into()); - } - - if self.options.builtins { - output_vector.push("--builtins".into()); - } - - if let Some(ref prefix) = self.options.ctypes_prefix { - output_vector.push("--ctypes-prefix".into()); - output_vector.push(prefix.clone()); - } - - if self.options.emit_ast { - output_vector.push("--emit-clang-ast".into()); - } - - if self.options.emit_ir { - output_vector.push("--emit-ir".into()); - } - if let Some(ref graph) = self.options.emit_ir_graphviz { - output_vector.push("--emit-ir-graphviz".into()); - output_vector.push(graph.clone()) - } - if self.options.enable_cxx_namespaces { - output_vector.push("--enable-cxx-namespaces".into()); - } - if self.options.disable_name_namespacing { - output_vector.push("--disable-name-namespacing".into()); - } - - if !self.options.codegen_config.functions { - output_vector.push("--ignore-functions".into()); - } - - output_vector.push("--generate".into()); - - //Temporary placeholder for below 4 options - let mut options: Vec = Vec::new(); - if self.options.codegen_config.functions { - options.push("function".into()); - } - if self.options.codegen_config.types { - options.push("types".into()); - } - if self.options.codegen_config.vars { - options.push("vars".into()); - } - if self.options.codegen_config.methods { - options.push("methods".into()); - } - if self.options.codegen_config.constructors { - options.push("constructors".into()); - } - if self.options.codegen_config.destructors { - options.push("destructors".into()); - } - - output_vector.push(options.join(",")); - - if !self.options.codegen_config.methods { - output_vector.push("--ignore-methods".into()); - } - - if !self.options.convert_floats { - output_vector.push("--no-convert-floats".into()); - } - - if !self.options.prepend_enum_name { - output_vector.push("--no-prepend-enum-name".into()); - } - - self.options - .opaque_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--opaque-type".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .raw_lines - .iter() - .map(|item| { - output_vector.push("--raw-line".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - if self.options.use_core { - output_vector.push("--use-core".into()); - } - - if self.options.conservative_inline_namespaces { - output_vector.push("--conservative-inline-namespaces".into()); - } - - self.options - .whitelisted_functions - .get_items() - .iter() - .map(|item| { - output_vector.push("--whitelist-function".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .whitelisted_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--whitelist-type".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .whitelisted_vars - .get_items() - .iter() - .map(|item| { - output_vector.push("--whitelist-var".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - output_vector.push("--".into()); - - if !self.options.clang_args.is_empty() { - output_vector.extend(self.options.clang_args.iter().cloned()); - } - - if self.input_headers.len() > 1 { - output_vector.extend( - self.input_headers[..self.input_headers.len() - 1] - .iter() - .cloned(), - ); - } - - if !self.options.rustfmt_bindings { - output_vector.push("--no-rustfmt-bindings".into()); - } - - if let Some(path) = self.options - .rustfmt_configuration_file - .as_ref() - .and_then(|f| f.to_str()) - { - output_vector.push("--rustfmt-configuration-file".into()); - output_vector.push(path.into()); - } - - self.options - .no_partialeq_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--no-partialeq".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .no_copy_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--no-copy".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - self.options - .no_hash_types - .get_items() - .iter() - .map(|item| { - output_vector.push("--no-hash".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - - output_vector - } - - /// Add an input C/C++ header to generate bindings for. - /// - /// This can be used to generate bindings to a single header: - /// - /// ```ignore - /// let bindings = bindgen::Builder::default() - /// .header("input.h") - /// .generate() - /// .unwrap(); - /// ``` - /// - /// Or you can invoke it multiple times to generate bindings to multiple - /// headers: - /// - /// ```ignore - /// let bindings = bindgen::Builder::default() - /// .header("first.h") - /// .header("second.h") - /// .header("third.h") - /// .generate() - /// .unwrap(); - /// ``` - pub fn header>(mut self, header: T) -> Builder { - self.input_headers.push(header.into()); - self - } - - /// Add `contents` as an input C/C++ header named `name`. - /// - /// The file `name` will be added to the clang arguments. - pub fn header_contents(mut self, name: &str, contents: &str) -> Builder { - self.input_header_contents.push( - (name.into(), contents.into()), - ); - self - } - - /// Specify the rust target - /// - /// The default is the latest stable Rust version - pub fn rust_target(mut self, rust_target: RustTarget) -> Self { - self.options.set_rust_target(rust_target); - self - } - - /// Disable support for native Rust unions, if supported. - pub fn disable_untagged_union(mut self) -> Self { - self.options.rust_features.untagged_union = false; - self - } - - /// Set the output graphviz file. - pub fn emit_ir_graphviz>(mut self, path: T) -> Builder { - let path = path.into(); - self.options.emit_ir_graphviz = Some(path); - self - } - - /// Whether the generated bindings should contain documentation comments or - /// not. - /// - /// This ideally will always be true, but it may need to be false until we - /// implement some processing on comments to work around issues as described - /// in: - /// - /// https://github.com/rust-lang-nursery/rust-bindgen/issues/426 - pub fn generate_comments(mut self, doit: bool) -> Self { - self.options.generate_comments = doit; - self - } - - /// Whether to whitelist recursively or not. Defaults to true. - /// - /// Given that we have explicitly whitelisted the "initiate_dance_party" - /// function in this C header: - /// - /// ```c - /// typedef struct MoonBoots { - /// int bouncy_level; - /// } MoonBoots; - /// - /// void initiate_dance_party(MoonBoots* boots); - /// ``` - /// - /// We would normally generate bindings to both the `initiate_dance_party` - /// function and the `MoonBoots` struct that it transitively references. By - /// configuring with `whitelist_recursively(false)`, `bindgen` will not emit - /// bindings for anything except the explicitly whitelisted items, and there - /// would be no emitted struct definition for `MoonBoots`. However, the - /// `initiate_dance_party` function would still reference `MoonBoots`! - /// - /// **Disabling this feature will almost certainly cause `bindgen` to emit - /// bindings that will not compile!** If you disable this feature, then it - /// is *your* responsiblity to provide definitions for every type that is - /// referenced from an explicitly whitelisted item. One way to provide the - /// definitions is by using the [`Builder::raw_line`](#method.raw_line) - /// method, another would be to define them in Rust and then `include!(...)` - /// the bindings immediately afterwards. - pub fn whitelist_recursively(mut self, doit: bool) -> Self { - self.options.whitelist_recursively = doit; - self - } - - /// Generate `#[macro_use] extern crate objc;` instead of `use objc;` - /// in the prologue of the files generated from objective-c files - pub fn objc_extern_crate(mut self, doit: bool) -> Self { - self.options.objc_extern_crate = doit; - self - } - - /// Whether to use the clang-provided name mangling. This is true by default - /// and probably needed for C++ features. - /// - /// However, some old libclang versions seem to return incorrect results in - /// some cases for non-mangled functions, see [1], so we allow disabling it. - /// - /// [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/528 - pub fn trust_clang_mangling(mut self, doit: bool) -> Self { - self.options.enable_mangling = doit; - self - } - - /// Hide the given type from the generated bindings. Regular expressions are - /// supported. - #[deprecated(note = "Use blacklist_type instead")] - pub fn hide_type>(self, arg: T) -> Builder { - self.blacklist_type(arg) - } - - /// Hide the given type from the generated bindings. Regular expressions are - /// supported. - pub fn blacklist_type>(mut self, arg: T) -> Builder { - self.options.blacklisted_types.insert(arg); - self - } - - /// Treat the given type as opaque in the generated bindings. Regular - /// expressions are supported. - pub fn opaque_type>(mut self, arg: T) -> Builder { - self.options.opaque_types.insert(arg); - self - } - - /// Whitelist the given type so that it (and all types that it transitively - /// refers to) appears in the generated bindings. Regular expressions are - /// supported. - #[deprecated(note = "use whitelist_type instead")] - pub fn whitelisted_type>(self, arg: T) -> Builder { - self.whitelist_type(arg) - } - - /// Whitelist the given type so that it (and all types that it transitively - /// refers to) appears in the generated bindings. Regular expressions are - /// supported. - pub fn whitelist_type>(mut self, arg: T) -> Builder { - self.options.whitelisted_types.insert(arg); - self - } - - /// Whitelist the given function so that it (and all types that it - /// transitively refers to) appears in the generated bindings. Regular - /// expressions are supported. - pub fn whitelist_function>(mut self, arg: T) -> Builder { - self.options.whitelisted_functions.insert(arg); - self - } - - /// Whitelist the given function. - /// - /// Deprecated: use whitelist_function instead. - #[deprecated(note = "use whitelist_function instead")] - pub fn whitelisted_function>(self, arg: T) -> Builder { - self.whitelist_function(arg) - } - - /// Whitelist the given variable so that it (and all types that it - /// transitively refers to) appears in the generated bindings. Regular - /// expressions are supported. - pub fn whitelist_var>(mut self, arg: T) -> Builder { - self.options.whitelisted_vars.insert(arg); - self - } - - /// Whitelist the given variable. - /// - /// Deprecated: use whitelist_var instead. - #[deprecated(note = "use whitelist_var instead")] - pub fn whitelisted_var>(self, arg: T) -> Builder { - self.whitelist_var(arg) - } - - - /// Mark the given enum (or set of enums, if using a pattern) as being - /// bitfield-like. Regular expressions are supported. - /// - /// This makes bindgen generate a type that isn't a rust `enum`. Regular - /// expressions are supported. - pub fn bitfield_enum>(mut self, arg: T) -> Builder { - self.options.bitfield_enums.insert(arg); - self - } - - /// Mark the given enum (or set of enums, if using a pattern) as a Rust - /// enum. - /// - /// This makes bindgen generate enums instead of constants. Regular - /// expressions are supported. - /// - /// **Use this with caution.** You should not be using Rust enums unless - /// you have complete control of the C/C++ code that you're binding to. - /// Take a look at https://github.com/rust-lang/rust/issues/36927 for - /// more information. - pub fn rustified_enum>(mut self, arg: T) -> Builder { - self.options.rustified_enums.insert(arg); - self - } - - /// Mark the given enum (or set of enums, if using a pattern) as a set of - /// constants that should be put into a module. - /// - /// This makes bindgen generate modules containing constants instead of - /// just constants. Regular expressions are supported. - pub fn constified_enum_module>(mut self, arg: T) -> Builder { - self.options.constified_enum_modules.insert(arg); - self - } - - /// Add a string to prepend to the generated bindings. The string is passed - /// through without any modification. - pub fn raw_line>(mut self, arg: T) -> Builder { - self.options.raw_lines.push(arg.into()); - self - } - - /// Add an argument to be passed straight through to clang. - pub fn clang_arg>(mut self, arg: T) -> Builder { - self.options.clang_args.push(arg.into()); - self - } - - /// Add arguments to be passed straight through to clang. - pub fn clang_args(mut self, iter: I) -> Builder - where - I: IntoIterator, - I::Item: AsRef, - { - for arg in iter { - self = self.clang_arg(arg.as_ref()) - } - self - } - - /// Emit bindings for builtin definitions (for example `__builtin_va_list`) - /// in the generated Rust. - pub fn emit_builtins(mut self) -> Builder { - self.options.builtins = true; - self - } - - /// Avoid converting floats to `f32`/`f64` by default. - pub fn no_convert_floats(mut self) -> Self { - self.options.convert_floats = false; - self - } - - /// Set whether layout tests should be generated. - pub fn layout_tests(mut self, doit: bool) -> Self { - self.options.layout_tests = doit; - self - } - - /// Set whether `Debug` should be implemented, if it can not be derived automatically. - pub fn impl_debug(mut self, doit: bool) -> Self { - self.options.impl_debug = doit; - self - } - - /// Set whether `PartialEq` should be implemented, if it can not be derived automatically. - pub fn impl_partialeq(mut self, doit: bool) -> Self { - self.options.impl_partialeq = doit; - self - } - - /// Set whether `Copy` should be derived by default. - pub fn derive_copy(mut self, doit: bool) -> Self { - self.options.derive_copy = doit; - self - } - - /// Set whether `Debug` should be derived by default. - pub fn derive_debug(mut self, doit: bool) -> Self { - self.options.derive_debug = doit; - self - } - - /// Set whether `Default` should be derived by default. - pub fn derive_default(mut self, doit: bool) -> Self { - self.options.derive_default = doit; - self - } - - /// Set whether `Hash` should be derived by default. - pub fn derive_hash(mut self, doit: bool) -> Self { - self.options.derive_hash = doit; - self - } - - /// Set whether `PartialOrd` should be derived by default. - /// If we don't compute partialord, we also cannot compute - /// ord. Set the derive_ord to `false` when doit is `false`. - pub fn derive_partialord(mut self, doit: bool) -> Self { - self.options.derive_partialord = doit; - if !doit { - self.options.derive_ord = false; - } - self - } - - /// Set whether `Ord` should be derived by default. - /// We can't compute `Ord` without computing `PartialOrd`, - /// so we set the same option to derive_partialord. - pub fn derive_ord(mut self, doit: bool) -> Self { - self.options.derive_ord = doit; - self.options.derive_partialord = doit; - self - } - - /// Set whether `PartialEq` should be derived by default. - /// - /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving - /// `Eq` is also disabled when `doit` is `false`. - pub fn derive_partialeq(mut self, doit: bool) -> Self { - self.options.derive_partialeq = doit; - if !doit { - self.options.derive_eq = false; - } - self - } - - /// Set whether `Eq` should be derived by default. - /// - /// We can't derive `Eq` without also deriving `PartialEq`, so we also - /// enable deriving `PartialEq` when `doit` is `true`. - pub fn derive_eq(mut self, doit: bool) -> Self { - self.options.derive_eq = doit; - if doit { - self.options.derive_partialeq = doit; - } - self - } - - /// Set whether or not to time bindgen phases, and print information to - /// stderr. - pub fn time_phases(mut self, doit: bool) -> Self { - self.options.time_phases = doit; - self - } - - /// Emit Clang AST. - pub fn emit_clang_ast(mut self) -> Builder { - self.options.emit_ast = true; - self - } - - /// Emit IR. - pub fn emit_ir(mut self) -> Builder { - self.options.emit_ir = true; - self - } - - /// Enable C++ namespaces. - pub fn enable_cxx_namespaces(mut self) -> Builder { - self.options.enable_cxx_namespaces = true; - self - } - - /// Disable name auto-namespacing. - /// - /// By default, bindgen mangles names like `foo::bar::Baz` to look like - /// `foo_bar_Baz` instead of just `Baz`. - /// - /// This method disables that behavior. - /// - /// Note that this intentionally does not change the names used for - /// whitelisting and blacklisting, which should still be mangled with the - /// namespaces. - /// - /// Note, also, that this option may cause bindgen to generate duplicate - /// names. - pub fn disable_name_namespacing(mut self) -> Builder { - self.options.disable_name_namespacing = true; - self - } - - /// Treat inline namespaces conservatively. - /// - /// This is tricky, because in C++ is technically legal to override an item - /// defined in an inline namespace: - /// - /// ```cpp - /// inline namespace foo { - /// using Bar = int; - /// } - /// using Bar = long; - /// ``` - /// - /// Even though referencing `Bar` is a compiler error. - /// - /// We want to support this (arguably esoteric) use case, but we don't want - /// to make the rest of bindgen users pay an usability penalty for that. - /// - /// To support this, we need to keep all the inline namespaces around, but - /// then bindgen usage is a bit more difficult, because you cannot - /// reference, e.g., `std::string` (you'd need to use the proper inline - /// namespace). - /// - /// We could complicate a lot of the logic to detect name collisions, and if - /// not detected generate a `pub use inline_ns::*` or something like that. - /// - /// That's probably something we can do if we see this option is needed in a - /// lot of cases, to improve it's usability, but my guess is that this is - /// not going to be too useful. - pub fn conservative_inline_namespaces(mut self) -> Builder { - self.options.conservative_inline_namespaces = true; - self - } - - /// Whether inline functions should be generated or not. - /// - /// Note that they will usually not work. However you can use - /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are - /// responsible of compiling the library to make them callable. - pub fn generate_inline_functions(mut self, doit: bool) -> Self { - self.options.generate_inline_functions = doit; - self - } - - /// Ignore functions. - pub fn ignore_functions(mut self) -> Builder { - self.options.codegen_config.functions = false; - self - } - - /// Ignore methods. - pub fn ignore_methods(mut self) -> Builder { - self.options.codegen_config.methods = false; - self - } - - /// Avoid generating any unstable Rust, such as Rust unions, in the generated bindings. - #[deprecated(note = "please use `rust_target` instead")] - pub fn unstable_rust(self, doit: bool) -> Self { - let rust_target = if doit { - RustTarget::Nightly - } else { - LATEST_STABLE_RUST - }; - self.rust_target(rust_target) - } - - /// Use core instead of libstd in the generated bindings. - pub fn use_core(mut self) -> Builder { - self.options.use_core = true; - self - } - - /// Use the given prefix for the raw types instead of `::std::os::raw`. - pub fn ctypes_prefix>(mut self, prefix: T) -> Builder { - self.options.ctypes_prefix = Some(prefix.into()); - self - } - - /// Allows configuring types in different situations, see the - /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation. - pub fn parse_callbacks( - mut self, - cb: Box, - ) -> Self { - self.options.parse_callbacks = Some(cb); - self - } - - /// Choose what to generate using a - /// [`CodegenConfig`](./struct.CodegenConfig.html). - pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self { - self.options.codegen_config = config; - self - } - - /// Prepend the enum name to constant or bitfield variants. - pub fn prepend_enum_name(mut self, doit: bool) -> Self { - self.options.prepend_enum_name = doit; - self - } - - /// Set whether rustfmt should format the generated bindings. - pub fn rustfmt_bindings(mut self, doit: bool) -> Self { - self.options.rustfmt_bindings = doit; - self - } - - /// Set the absolute path to the rustfmt configuration file, if None, the standard rustfmt - /// options are used. - pub fn rustfmt_configuration_file(mut self, path: Option) -> Self { - self = self.rustfmt_bindings(true); - self.options.rustfmt_configuration_file = path; - self - } - - /// Sets an explicit path to rustfmt, to be used when rustfmt is enabled. - pub fn with_rustfmt>(mut self, path: P) -> Self { - self.options.rustfmt_path = Some(path.into()); - self - } - - /// Generate the Rust bindings using the options built up thus far. - pub fn generate(mut self) -> Result { - self.options.input_header = self.input_headers.pop(); - self.options.clang_args.extend( - self.input_headers - .drain(..) - .flat_map(|header| { - iter::once("-include".into()).chain(iter::once(header)) - }), - ); - - self.options.input_unsaved_files.extend( - self.input_header_contents.drain(..).map(|(name, contents)| { - clang::UnsavedFile::new(&name, &contents) - }), - ); - - Bindings::generate(self.options) - } - - /// Preprocess and dump the input header files to disk. - /// - /// This is useful when debugging bindgen, using C-Reduce, or when filing - /// issues. The resulting file will be named something like `__bindgen.i` or - /// `__bindgen.ii` - pub fn dump_preprocessed_input(&self) -> io::Result<()> { - fn check_is_cpp(name_file: &str) -> bool { - name_file.ends_with(".hpp") || name_file.ends_with(".hxx") - || name_file.ends_with(".hh") - || name_file.ends_with(".h++") - } - - let clang = clang_sys::support::Clang::find(None, &[]).ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Cannot find clang executable") - })?; - - // The contents of a wrapper file that includes all the input header - // files. - let mut wrapper_contents = String::new(); - - // Whether we are working with C or C++ inputs. - let mut is_cpp = self.options.clang_args.windows(2).any(|w| { - w[0] == "-x=c++" || w[1] == "-x=c++" || w == &["-x", "c++"] - }); - - // For each input header, add `#include "$header"`. - for header in &self.input_headers { - is_cpp |= check_is_cpp(header); - - wrapper_contents.push_str("#include \""); - wrapper_contents.push_str(header); - wrapper_contents.push_str("\"\n"); - } - - // For each input header content, add a prefix line of `#line 0 "$name"` - // followed by the contents. - for &(ref name, ref contents) in &self.input_header_contents { - is_cpp |= check_is_cpp(name); - - wrapper_contents.push_str("#line 0 \""); - wrapper_contents.push_str(name); - wrapper_contents.push_str("\"\n"); - wrapper_contents.push_str(contents); - } - - let wrapper_path = PathBuf::from(if is_cpp { - "__bindgen.cpp" - } else { - "__bindgen.c" - }); - - { - let mut wrapper_file = File::create(&wrapper_path)?; - wrapper_file.write(wrapper_contents.as_bytes())?; - } - - let mut cmd = Command::new(&clang.path); - cmd.arg("-save-temps") - .arg("-E") - .arg("-C") - .arg("-c") - .arg(&wrapper_path) - .stdout(Stdio::piped()); - - for a in &self.options.clang_args { - cmd.arg(a); - } - - let mut child = cmd.spawn()?; - - let mut preprocessed = child.stdout.take().unwrap(); - let mut file = File::create(if is_cpp { - "__bindgen.ii" - } else { - "__bindgen.i" - })?; - io::copy(&mut preprocessed, &mut file)?; - - if child.wait()?.success() { - Ok(()) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - "clang exited with non-zero status", - )) - } - } - - /// Don't derive `PartialEq` for a given type. Regular - /// expressions are supported. - pub fn no_partialeq>(mut self, arg: T) -> Builder { - self.options.no_partialeq_types.insert(arg.into()); - self - } - - /// Don't derive `Copy` for a given type. Regular - /// expressions are supported. - pub fn no_copy>(mut self, arg: T) -> Self { - self.options.no_copy_types.insert(arg.into()); - self - } - - /// Don't derive `Hash` for a given type. Regular - /// expressions are supported. - pub fn no_hash>(mut self, arg: T) -> Builder { - self.options.no_hash_types.insert(arg.into()); - self - } -} - -/// Configuration options for generated bindings. -#[derive(Debug)] -struct BindgenOptions { - /// The set of types that have been blacklisted and should not appear - /// anywhere in the generated code. - blacklisted_types: RegexSet, - - /// The set of types that should be treated as opaque structures in the - /// generated code. - opaque_types: RegexSet, - - /// The explicit rustfmt path. - rustfmt_path: Option, - - /// The set of types that we should have bindings for in the generated - /// code. - /// - /// This includes all types transitively reachable from any type in this - /// set. One might think of whitelisted types/vars/functions as GC roots, - /// and the generated Rust code as including everything that gets marked. - whitelisted_types: RegexSet, - - /// Whitelisted functions. See docs for `whitelisted_types` for more. - whitelisted_functions: RegexSet, - - /// Whitelisted variables. See docs for `whitelisted_types` for more. - whitelisted_vars: RegexSet, - - /// The enum patterns to mark an enum as bitfield. - bitfield_enums: RegexSet, - - /// The enum patterns to mark an enum as a Rust enum. - rustified_enums: RegexSet, - - /// The enum patterns to mark an enum as a module of constants. - constified_enum_modules: RegexSet, - - /// Whether we should generate builtins or not. - builtins: bool, - - /// True if we should dump the Clang AST for debugging purposes. - emit_ast: bool, - - /// True if we should dump our internal IR for debugging purposes. - emit_ir: bool, - - /// Output graphviz dot file. - emit_ir_graphviz: Option, - - /// True if we should emulate C++ namespaces with Rust modules in the - /// generated bindings. - enable_cxx_namespaces: bool, - - /// True if we should avoid mangling names with namespaces. - disable_name_namespacing: bool, - - /// True if we should generate layout tests for generated structures. - layout_tests: bool, - - /// True if we should implement the Debug trait for C/C++ structures and types - /// that do not support automatically deriving Debug. - impl_debug: bool, - - /// True if we should implement the PartialEq trait for C/C++ structures and types - /// that do not support autoamically deriving PartialEq. - impl_partialeq: bool, - - /// True if we should derive Copy trait implementations for C/C++ structures - /// and types. - derive_copy: bool, - - /// True if we should derive Debug trait implementations for C/C++ structures - /// and types. - derive_debug: bool, - - /// True if we should derive Default trait implementations for C/C++ structures - /// and types. - derive_default: bool, - - /// True if we should derive Hash trait implementations for C/C++ structures - /// and types. - derive_hash: bool, - - /// True if we should derive PartialOrd trait implementations for C/C++ structures - /// and types. - derive_partialord: bool, - - /// True if we should derive Ord trait implementations for C/C++ structures - /// and types. - derive_ord: bool, - - /// True if we should derive PartialEq trait implementations for C/C++ structures - /// and types. - derive_partialeq: bool, - - /// True if we should derive Eq trait implementations for C/C++ structures - /// and types. - derive_eq: bool, - - /// True if we should avoid using libstd to use libcore instead. - use_core: bool, - - /// An optional prefix for the "raw" types, like `c_int`, `c_void`... - ctypes_prefix: Option, - - /// Whether to time the bindgen phases. - time_phases: bool, - - /// True if we should generate constant names that are **directly** under - /// namespaces. - namespaced_constants: bool, - - /// True if we should use MSVC name mangling rules. - msvc_mangling: bool, - - /// Whether we should convert float types to f32/f64 types. - convert_floats: bool, - - /// The set of raw lines to prepend to the generated Rust code. - raw_lines: Vec, - - /// The set of arguments to pass straight through to Clang. - clang_args: Vec, - - /// The input header file. - input_header: Option, - - /// Unsaved files for input. - input_unsaved_files: Vec, - - /// A user-provided visitor to allow customizing different kinds of - /// situations. - parse_callbacks: Option>, - - /// Which kind of items should we generate? By default, we'll generate all - /// of them. - codegen_config: CodegenConfig, - - /// Whether to treat inline namespaces conservatively. - /// - /// See the builder method description for more details. - conservative_inline_namespaces: bool, - - /// Wether to keep documentation comments in the generated output. See the - /// documentation for more details. - generate_comments: bool, - - /// Whether to generate inline functions. Defaults to false. - generate_inline_functions: bool, - - /// Wether to whitelist types recursively. Defaults to true. - whitelist_recursively: bool, - - /// Intead of emitting 'use objc;' to files generated from objective c files, - /// generate '#[macro_use] extern crate objc;' - objc_extern_crate: bool, - - /// Whether to use the clang-provided name mangling. This is true and - /// probably needed for C++ features. - /// - /// However, some old libclang versions seem to return incorrect results in - /// some cases for non-mangled functions, see [1], so we allow disabling it. - /// - /// [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/528 - enable_mangling: bool, - - /// Whether to prepend the enum name to bitfield or constant variants. - prepend_enum_name: bool, - - /// Version of the Rust compiler to target - rust_target: RustTarget, - - /// Features to enable, derived from `rust_target` - rust_features: RustFeatures, - - /// Whether rustfmt should format the generated bindings. - rustfmt_bindings: bool, - - /// The absolute path to the rustfmt configuration file, if None, the standard rustfmt - /// options are used. - - rustfmt_configuration_file: Option, - - /// The set of types that we should not derive `PartialEq` for. - no_partialeq_types: RegexSet, - - /// The set of types that we should not derive `Copy` for. - no_copy_types: RegexSet, - - /// The set of types that we should not derive `Hash` for. - no_hash_types: RegexSet, -} - -/// TODO(emilio): This is sort of a lie (see the error message that results from -/// removing this), but since we don't share references across panic boundaries -/// it's ok. -impl ::std::panic::UnwindSafe for BindgenOptions {} - -impl BindgenOptions { - fn build(&mut self) { - self.whitelisted_vars.build(); - self.whitelisted_types.build(); - self.whitelisted_functions.build(); - self.blacklisted_types.build(); - self.opaque_types.build(); - self.bitfield_enums.build(); - self.constified_enum_modules.build(); - self.rustified_enums.build(); - self.no_partialeq_types.build(); - self.no_copy_types.build(); - self.no_hash_types.build(); - } - - /// Update rust target version - pub fn set_rust_target(&mut self, rust_target: RustTarget) { - self.rust_target = rust_target; - - // Keep rust_features synced with rust_target - self.rust_features = rust_target.into(); - } - - /// Get features supported by target Rust version - pub fn rust_features(&self) -> RustFeatures { - self.rust_features - } -} - -impl Default for BindgenOptions { - fn default() -> BindgenOptions { - let rust_target = RustTarget::default(); - - BindgenOptions { - rust_target: rust_target, - rust_features: rust_target.into(), - blacklisted_types: Default::default(), - opaque_types: Default::default(), - rustfmt_path: Default::default(), - whitelisted_types: Default::default(), - whitelisted_functions: Default::default(), - whitelisted_vars: Default::default(), - bitfield_enums: Default::default(), - rustified_enums: Default::default(), - constified_enum_modules: Default::default(), - builtins: false, - emit_ast: false, - emit_ir: false, - emit_ir_graphviz: None, - layout_tests: true, - impl_debug: false, - impl_partialeq: false, - derive_copy: true, - derive_debug: true, - derive_default: false, - derive_hash: false, - derive_partialord: false, - derive_ord: false, - derive_partialeq: false, - derive_eq: false, - enable_cxx_namespaces: false, - disable_name_namespacing: false, - use_core: false, - ctypes_prefix: None, - namespaced_constants: true, - msvc_mangling: false, - convert_floats: true, - raw_lines: vec![], - clang_args: vec![], - input_header: None, - input_unsaved_files: vec![], - parse_callbacks: None, - codegen_config: CodegenConfig::all(), - conservative_inline_namespaces: false, - generate_comments: true, - generate_inline_functions: false, - whitelist_recursively: true, - objc_extern_crate: false, - enable_mangling: true, - prepend_enum_name: true, - time_phases: false, - rustfmt_bindings: true, - rustfmt_configuration_file: None, - no_partialeq_types: Default::default(), - no_copy_types: Default::default(), - no_hash_types: Default::default(), - } - } -} - -fn ensure_libclang_is_loaded() { - if clang_sys::is_loaded() { - return; - } - - // XXX (issue #350): Ensure that our dynamically loaded `libclang` - // doesn't get dropped prematurely, nor is loaded multiple times - // across different threads. - - lazy_static! { - static ref LIBCLANG: Arc = { - clang_sys::load().expect("Unable to find libclang"); - clang_sys::get_library() - .expect("We just loaded libclang and it had better still be \ - here!") - }; - } - - clang_sys::set_library(Some(LIBCLANG.clone())); -} - -/// Generated Rust bindings. -#[derive(Debug)] -pub struct Bindings { - options: BindgenOptions, - module: quote::Tokens, -} - -impl Bindings { - /// Generate bindings for the given options. - pub(crate) fn generate( - mut options: BindgenOptions, - ) -> Result { - ensure_libclang_is_loaded(); - - options.build(); - - // Filter out include paths and similar stuff, so we don't incorrectly - // promote them to `-isystem`. - let clang_args_for_clang_sys = { - let mut last_was_include_prefix = false; - options.clang_args.iter().filter(|arg| { - if last_was_include_prefix { - last_was_include_prefix = false; - return false; - } - - let arg = &**arg; - - // https://clang.llvm.org/docs/ClangCommandLineReference.html - // -isystem and -isystem-after are harmless. - if arg == "-I" || arg == "--include-directory" { - last_was_include_prefix = true; - return false; - } - - if arg.starts_with("-I") || arg.starts_with("--include-directory=") { - return false; - } - - true - }).cloned().collect::>() - }; - - // TODO: Make this path fixup configurable? - if let Some(clang) = clang_sys::support::Clang::find( - None, - &clang_args_for_clang_sys, - ) - { - // If --target is specified, assume caller knows what they're doing - // and don't mess with include paths for them - let has_target_arg = options - .clang_args - .iter() - .rposition(|arg| arg.starts_with("--target")) - .is_some(); - if !has_target_arg { - // TODO: distinguish C and C++ paths? C++'s should be enough, I - // guess. - if let Some(cpp_search_paths) = clang.cpp_search_paths { - for path in cpp_search_paths.into_iter() { - if let Ok(path) = path.into_os_string().into_string() { - options.clang_args.push("-isystem".to_owned()); - options.clang_args.push(path); - } - } - } - } - } - - #[cfg(unix)] - fn can_read(perms: &std::fs::Permissions) -> bool { - use std::os::unix::fs::PermissionsExt; - perms.mode() & 0o444 > 0 - } - - #[cfg(not(unix))] - fn can_read(_: &std::fs::Permissions) -> bool { - true - } - - if let Some(h) = options.input_header.as_ref() { - if let Ok(md) = std::fs::metadata(h) { - if md.is_dir() { - eprintln!("error: '{}' is a folder", h); - return Err(()); - } - if !can_read(&md.permissions()) { - eprintln!("error: insufficient permissions to read '{}'", h); - return Err(()); - } - options.clang_args.push(h.clone()) - } else { - eprintln!("error: header '{}' does not exist.", h); - return Err(()); - } - } - - for f in options.input_unsaved_files.iter() { - options.clang_args.push(f.name.to_str().unwrap().to_owned()) - } - - let time_phases = options.time_phases; - let mut context = BindgenContext::new(options); - - { - let _t = time::Timer::new("parse") - .with_output(time_phases); - parse(&mut context)?; - } - - let (items, options) = codegen::codegen(context); - - Ok(Bindings { - options: options, - module: quote! { - #( #items )* - } - }) - } - - /// Convert these bindings into source text (with raw lines prepended). - pub fn to_string(&self) -> String { - let mut bytes = vec![]; - self.write(Box::new(&mut bytes) as Box) - .expect("writing to a vec cannot fail"); - String::from_utf8(bytes) - .expect("we should only write bindings that are valid utf-8") - } - - /// Write these bindings as source text to a file. - pub fn write_to_file>(&self, path: P) -> io::Result<()> { - let file = OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(path.as_ref())?; - self.write(Box::new(file))?; - Ok(()) - } - - /// Write these bindings as source text to the given `Write`able. - pub fn write<'a>(&self, mut writer: Box) -> io::Result<()> { - writer.write( - "/* automatically generated by rust-bindgen */\n\n".as_bytes(), - )?; - - for line in self.options.raw_lines.iter() { - writer.write(line.as_bytes())?; - writer.write("\n".as_bytes())?; - } - - if !self.options.raw_lines.is_empty() { - writer.write("\n".as_bytes())?; - } - - let bindings = self.module.to_string(); - - match self.rustfmt_generated_string(&bindings) { - Ok(rustfmt_bindings) => { - writer.write(rustfmt_bindings.as_bytes())?; - }, - Err(err) => { - eprintln!("{:?}", err); - writer.write(bindings.as_bytes())?; - }, - } - Ok(()) - } - - /// Checks if rustfmt_bindings is set and runs rustfmt on the string - fn rustfmt_generated_string<'a>( - &self, - source: &'a str, - ) -> io::Result> { - let _t = time::Timer::new("rustfmt_generated_string") - .with_output(self.options.time_phases); - - if !self.options.rustfmt_bindings { - return Ok(Cow::Borrowed(source)); - } - - let rustfmt = match self.options.rustfmt_path { - Some(ref p) => Cow::Borrowed(p), - None => { - let path = which::which("rustfmt") - .map_err(|e| { - io::Error::new(io::ErrorKind::Other, e.to_owned()) - })?; - - Cow::Owned(path) - } - }; - - let mut cmd = Command::new(&*rustfmt); - - cmd - .stdin(Stdio::piped()) - .stdout(Stdio::piped()); - - if let Some(path) = self.options - .rustfmt_configuration_file - .as_ref() - .and_then(|f| f.to_str()) - { - cmd.args(&["--config-path", path]); - } - - let mut child = cmd.spawn()?; - let mut child_stdin = child.stdin.take().unwrap(); - let mut child_stdout = child.stdout.take().unwrap(); - - let source = source.to_owned(); - - // Write to stdin in a new thread, so that we can read from stdout on this - // thread. This keeps the child from blocking on writing to its stdout which - // might block us from writing to its stdin. - let stdin_handle = ::std::thread::spawn(move || { - let _ = child_stdin.write_all(source.as_bytes()); - source - }); - - let mut output = vec![]; - io::copy(&mut child_stdout, &mut output)?; - - let status = child.wait()?; - let source = stdin_handle.join() - .expect("The thread writing to rustfmt's stdin doesn't do \ - anything that could panic"); - - match String::from_utf8(output) { - Ok(bindings) => { - match status.code() { - Some(0) => Ok(Cow::Owned(bindings)), - Some(2) => Err(io::Error::new( - io::ErrorKind::Other, - "Rustfmt parsing errors.".to_string(), - )), - Some(3) => { - warn!("Rustfmt could not format some lines."); - Ok(Cow::Owned(bindings)) - } - _ => Err(io::Error::new( - io::ErrorKind::Other, - "Internal rustfmt error".to_string(), - )), - } - }, - _ => Ok(Cow::Owned(source)) - } - } -} - -/// Determines whether the given cursor is in any of the files matched by the -/// options. -fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool { - ctx.options().builtins || !cursor.is_builtin() -} - -/// Parse one `Item` from the Clang cursor. -fn parse_one( - ctx: &mut BindgenContext, - cursor: clang::Cursor, - parent: Option, -) -> clang_sys::CXChildVisitResult { - if !filter_builtins(ctx, &cursor) { - return CXChildVisit_Continue; - } - - use clang_sys::CXChildVisit_Continue; - match Item::parse(cursor, parent, ctx) { - Ok(..) => {} - Err(ParseError::Continue) => {} - Err(ParseError::Recurse) => { - cursor.visit(|child| parse_one(ctx, child, parent)); - } - } - CXChildVisit_Continue -} - -/// Parse the Clang AST into our `Item` internal representation. -fn parse(context: &mut BindgenContext) -> Result<(), ()> { - use clang_sys::*; - - let mut any_error = false; - for d in context.translation_unit().diags().iter() { - let msg = d.format(); - let is_err = d.severity() >= CXDiagnostic_Error; - eprintln!("{}, err: {}", msg, is_err); - any_error |= is_err; - } - - if any_error { - return Err(()); - } - - let cursor = context.translation_unit().cursor(); - - if context.options().emit_ast { - - fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult { - if !cur.is_builtin() { - clang::ast_dump(&cur, 0) - } else { - CXChildVisit_Continue - } - } - cursor.visit(|cur| dump_if_not_builtin(&cur)); - } - - let root = context.root_module(); - context.with_module(root, |context| { - cursor.visit(|cursor| parse_one(context, cursor, None)) - }); - - assert!( - context.current_module() == context.root_module(), - "How did this happen?" - ); - Ok(()) -} - -/// Extracted Clang version data -#[derive(Debug)] -pub struct ClangVersion { - /// Major and minor semvar, if parsing was successful - pub parsed: Option<(u32, u32)>, - /// full version string - pub full: String, -} - -/// Get the major and the minor semvar numbers of Clang's version -pub fn clang_version() -> ClangVersion { - if !clang_sys::is_loaded() { - // TODO(emilio): Return meaningful error (breaking). - clang_sys::load().expect("Unable to find libclang"); - } - - let raw_v: String = clang::extract_clang_version(); - let split_v: Option> = raw_v.split_whitespace().nth(2).map(|v| { - v.split('.').collect() - }); - match split_v { - Some(v) => { - if v.len() >= 2 { - let maybe_major = v[0].parse::(); - let maybe_minor = v[1].parse::(); - match (maybe_major, maybe_minor) { - (Ok(major), Ok(minor)) => { - return ClangVersion { - parsed: Some((major, minor)), - full: raw_v.clone(), - } - } - _ => {} - } - } - } - None => {} - }; - ClangVersion { - parsed: None, - full: raw_v.clone(), - } -} - -/// Test command_line_flag function. -#[test] -fn commandline_flag_unit_test_function() { - //Test 1 - let bindings = ::builder(); - let command_line_flags = bindings.command_line_flags(); - - let test_cases = vec![ - "--rust-target", - "--no-derive-default", - "--generate", - "function,types,vars,methods,constructors,destructors", - ].iter() - .map(|&x| x.into()) - .collect::>(); - - assert!(test_cases.iter().all( - |ref x| command_line_flags.contains(x), - )); - - //Test 2 - let bindings = ::builder() - .header("input_header") - .whitelist_type("Distinct_Type") - .whitelist_function("safe_function"); - - let command_line_flags = bindings.command_line_flags(); - let test_cases = vec![ - "--rust-target", - "input_header", - "--no-derive-default", - "--generate", - "function,types,vars,methods,constructors,destructors", - "--whitelist-type", - "Distinct_Type", - "--whitelist-function", - "safe_function", - ].iter() - .map(|&x| x.into()) - .collect::>(); - println!("{:?}", command_line_flags); - - assert!(test_cases.iter().all( - |ref x| command_line_flags.contains(x), - )); - -} diff --git a/src/log_stubs.rs b/src/log_stubs.rs deleted file mode 100644 index 4a72d9a5ea..0000000000 --- a/src/log_stubs.rs +++ /dev/null @@ -1,30 +0,0 @@ -macro_rules! log { - (target: $target:expr, $lvl:expr, $($arg:tt)+) => { - let _ = $target; - let _ = log!($lvl, $($arg)+); - }; - ($lvl:expr, $($arg:tt)+) => {{ - let _ = $lvl; - let _ = format_args!($($arg)+); - }}; -} -macro_rules! error { - (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }; - ($($arg:tt)*) => { log!("", $($arg)*); }; -} -macro_rules! warn { - (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }; - ($($arg:tt)*) => { log!("", $($arg)*); }; -} -macro_rules! info { - (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }; - ($($arg:tt)*) => { log!("", $($arg)*); }; -} -macro_rules! debug { - (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }; - ($($arg:tt)*) => { log!("", $($arg)*); }; -} -macro_rules! trace { - (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }; - ($($arg:tt)*) => { log!("", $($arg)*); }; -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index a0e0f6bff8..0000000000 --- a/src/main.rs +++ /dev/null @@ -1,82 +0,0 @@ -extern crate bindgen; -#[cfg(feature = "logging")] -extern crate env_logger; -#[macro_use] -#[cfg(feature = "logging")] -extern crate log; -extern crate clap; - -use bindgen::clang_version; -use std::env; -use std::panic; - -#[macro_use] -#[cfg(not(feature = "logging"))] -mod log_stubs; - -mod options; -use options::builder_from_flags; - -pub fn main() { - #[cfg(feature = "logging")] - env_logger::init(); - - let bind_args: Vec<_> = env::args().collect(); - - let version = clang_version(); - let expected_version = if cfg!(feature = "testing_only_libclang_4") { - (4, 0) - } else if cfg!(feature = "testing_only_libclang_3_8") { - (3, 8) - } else { - // Default to 3.9. - (3, 9) - }; - - info!("Clang Version: {}", version.full); - - match version.parsed { - None => warn!("Couldn't parse libclang version"), - Some(version) if version != expected_version => { - warn!("Using clang {:?}, expected {:?}", version, expected_version); - } - _ => {} - } - - match builder_from_flags(bind_args.into_iter()) { - Ok((builder, output, verbose)) => { - - let builder_result = panic::catch_unwind(|| { - builder.generate().expect("Unable to generate bindings") - }); - - if builder_result.is_err() { - if verbose { - print_verbose_err(); - } - std::process::exit(1); - } - - let bindings = builder_result.unwrap(); - bindings.write(output).expect("Unable to write output"); - } - Err(error) => { - println!("{}", error); - std::process::exit(1); - } - }; -} - -fn print_verbose_err() { - println!("Bindgen unexpectedly panicked"); - println!( - "This may be caused by one of the known-unsupported \ - things (https://github.com/rust-lang-nursery/rust-bindgen#c), \ - please modify the bindgen flags to work around it as \ - described in https://github.com/rust-lang-nursery/rust-bindgen#c" - ); - println!( - "Otherwise, please file an issue at \ - https://github.com/rust-lang-nursery/rust-bindgen/issues/new" - ); -} diff --git a/src/options.rs b/src/options.rs deleted file mode 100644 index b3ddbbfdb3..0000000000 --- a/src/options.rs +++ /dev/null @@ -1,574 +0,0 @@ -use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder}; -use clap::{App, Arg}; -use std::fs::File; -use std::io::{self, Error, ErrorKind, Write, stderr}; -use std::path::PathBuf; -use std::str::FromStr; - -/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. -pub fn builder_from_flags( - args: I, -) -> Result<(Builder, Box, bool), io::Error> -where - I: Iterator, -{ - let rust_target_help = format!( - "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.", - RUST_TARGET_STRINGS, - String::from(RustTarget::default()) - ); - - let matches = App::new("bindgen") - .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")) - .about("Generates Rust bindings from C/C++ headers.") - .usage("bindgen [FLAGS] [OPTIONS]
-- ...") - .args(&[ - Arg::with_name("header") - .help("C or C++ header file") - .required(true), - Arg::with_name("bitfield-enum") - .long("bitfield-enum") - .help("Mark any enum whose name matches as a set of \ - bitfield flags instead of an enumeration.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("rustified-enum") - .long("rustified-enum") - .help("Mark any enum whose name matches as a Rust enum \ - instead of a set of constants.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("constified-enum-module") - .long("constified-enum-module") - .help("Mark any enum whose name matches as a module of \ - constants instead of just constants.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("blacklist-type") - .long("blacklist-type") - .help("Mark as hidden.") - .value_name("type") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("no-layout-tests") - .long("no-layout-tests") - .help("Avoid generating layout tests for any type."), - Arg::with_name("no-derive-copy") - .long("no-derive-copy") - .help("Avoid deriving Copy on any type."), - Arg::with_name("no-derive-debug") - .long("no-derive-debug") - .help("Avoid deriving Debug on any type."), - Arg::with_name("no-derive-default") - .long("no-derive-default") - .hidden(true) - .help("Avoid deriving Default on any type."), - Arg::with_name("impl-debug") - .long("impl-debug") - .help("Create Debug implementation, if it can not be derived \ - automatically."), - Arg::with_name("impl-partialeq") - .long("impl-partialeq") - .help("Create PartialEq implementation, if it can not be derived \ - automatically."), - Arg::with_name("with-derive-default") - .long("with-derive-default") - .help("Derive Default on any type."), - Arg::with_name("with-derive-hash") - .long("with-derive-hash") - .help("Derive hash on any type."), - Arg::with_name("with-derive-partialeq") - .long("with-derive-partialeq") - .help("Derive partialeq on any type."), - Arg::with_name("with-derive-partialord") - .long("with-derive-partialord") - .help("Derive partialord on any type."), - Arg::with_name("with-derive-eq") - .long("with-derive-eq") - .help("Derive eq on any type. Enable this option also \ - enables --with-derive-partialeq"), - Arg::with_name("with-derive-ord") - .long("with-derive-ord") - .help("Derive ord on any type. Enable this option also \ - enables --with-derive-partialord"), - Arg::with_name("no-doc-comments") - .long("no-doc-comments") - .help("Avoid including doc comments in the output, see: \ - https://github.com/rust-lang-nursery/rust-bindgen/issues/426"), - Arg::with_name("no-recursive-whitelist") - .long("no-recursive-whitelist") - .help("Disable whitelisting types recursively. This will cause \ - bindgen to emit Rust code that won't compile! See the \ - `bindgen::Builder::whitelist_recursively` method's \ - documentation for details."), - Arg::with_name("objc-extern-crate") - .long("objc-extern-crate") - .help("Use extern crate instead of use for objc."), - Arg::with_name("distrust-clang-mangling") - .long("distrust-clang-mangling") - .help("Do not trust the libclang-provided mangling"), - Arg::with_name("builtins") - .long("builtins") - .help("Output bindings for builtin definitions, e.g. \ - __builtin_va_list."), - Arg::with_name("ctypes-prefix") - .long("ctypes-prefix") - .help("Use the given prefix before raw types instead of \ - ::std::os::raw.") - .value_name("prefix") - .takes_value(true), - Arg::with_name("time-phases") - .long("time-phases") - .help("Time the different bindgen phases and print to stderr"), - // All positional arguments after the end of options marker, `--` - Arg::with_name("clang-args") - .multiple(true), - Arg::with_name("emit-clang-ast") - .long("emit-clang-ast") - .help("Output the Clang AST for debugging purposes."), - Arg::with_name("emit-ir") - .long("emit-ir") - .help("Output our internal IR for debugging purposes."), - Arg::with_name("emit-ir-graphviz") - .long("emit-ir-graphviz") - .help("Dump graphviz dot file.") - .value_name("path") - .takes_value(true), - Arg::with_name("enable-cxx-namespaces") - .long("enable-cxx-namespaces") - .help("Enable support for C++ namespaces."), - Arg::with_name("disable-name-namespacing") - .long("disable-name-namespacing") - .help("Disable namespacing via mangling, causing bindgen to \ - generate names like \"Baz\" instead of \"foo_bar_Baz\" \ - for an input name \"foo::bar::Baz\"."), - Arg::with_name("ignore-functions") - .long("ignore-functions") - .help("Do not generate bindings for functions or methods. This \ - is useful when you only care about struct layouts."), - Arg::with_name("generate") - .long("generate") - .help("Generate only given items, split by commas. \ - Valid values are \"functions\",\"types\", \"vars\", \ - \"methods\", \"constructors\" and \"destructors\".") - .takes_value(true), - Arg::with_name("ignore-methods") - .long("ignore-methods") - .help("Do not generate bindings for methods."), - Arg::with_name("no-convert-floats") - .long("no-convert-floats") - .help("Do not automatically convert floats to f32/f64."), - Arg::with_name("no-prepend-enum-name") - .long("no-prepend-enum-name") - .help("Do not prepend the enum name to bitfield or constant variants."), - Arg::with_name("unstable-rust") - .long("unstable-rust") - .help("Generate unstable Rust code (deprecated; use --rust-target instead).") - .multiple(true), // FIXME: Pass legacy test suite - Arg::with_name("opaque-type") - .long("opaque-type") - .help("Mark as opaque.") - .value_name("type") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("output") - .short("o") - .long("output") - .help("Write Rust bindings to .") - .takes_value(true), - Arg::with_name("raw-line") - .long("raw-line") - .help("Add a raw line of Rust code at the beginning of output.") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("rust-target") - .long("rust-target") - .help(&rust_target_help) - .takes_value(true), - Arg::with_name("use-core") - .long("use-core") - .help("Use types from Rust core instead of std."), - Arg::with_name("conservative-inline-namespaces") - .long("conservative-inline-namespaces") - .help("Conservatively generate inline namespaces to avoid name \ - conflicts."), - Arg::with_name("use-msvc-mangling") - .long("use-msvc-mangling") - .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."), - Arg::with_name("whitelist-function") - .long("whitelist-function") - .help("Whitelist all the free-standing functions matching \ - . Other non-whitelisted functions will not be \ - generated.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("generate-inline-functions") - .long("generate-inline-functions") - .help("Generate inline functions."), - Arg::with_name("whitelist-type") - .long("whitelist-type") - .help("Only generate types matching . Other non-whitelisted types will \ - not be generated.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("whitelist-var") - .long("whitelist-var") - .help("Whitelist all the free-standing variables matching \ - . Other non-whitelisted variables will not be \ - generated.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("verbose") - .long("verbose") - .help("Print verbose error messages."), - Arg::with_name("dump-preprocessed-input") - .long("dump-preprocessed-input") - .help("Preprocess and dump the input header files to disk. \ - Useful when debugging bindgen, using C-Reduce, or when \ - filing issues. The resulting file will be named \ - something like `__bindgen.i` or `__bindgen.ii`."), - Arg::with_name("no-rustfmt-bindings") - .long("no-rustfmt-bindings") - .help("Do not format the generated bindings with rustfmt."), - Arg::with_name("rustfmt-bindings") - .long("rustfmt-bindings") - .help("Format the generated bindings with rustfmt. DEPRECATED: \ - --rustfmt-bindings is now enabled by default. Disable \ - with --no-rustfmt-bindings."), - Arg::with_name("rustfmt-configuration-file") - .long("rustfmt-configuration-file") - .help("The absolute path to the rustfmt configuration file. \ - The configuration file will be used for formatting the bindings. \ - This parameter is incompatible with --no-rustfmt-bindings.") - .value_name("path") - .takes_value(true) - .multiple(false) - .number_of_values(1), - Arg::with_name("no-partialeq") - .long("no-partialeq") - .help("Avoid deriving PartialEq for types matching .") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("no-copy") - .long("no-copy") - .help("Avoid deriving Copy for types matching .") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("no-hash") - .long("no-hash") - .help("Avoid deriving Hash for types matching .") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - ]) // .args() - .get_matches_from(args); - - let mut builder = builder(); - - if let Some(header) = matches.value_of("header") { - builder = builder.header(header); - } else { - return Err(Error::new(ErrorKind::Other, "Header not found")); - } - - if matches.is_present("unstable-rust") { - builder = builder.rust_target(RustTarget::Nightly); - writeln!( - &mut stderr(), - "warning: the `--unstable-rust` option is deprecated" - ).expect("Unable to write error message"); - } - - if let Some(rust_target) = matches.value_of("rust-target") { - builder = builder.rust_target(RustTarget::from_str(rust_target)?); - } - - if let Some(bitfields) = matches.values_of("bitfield-enum") { - for regex in bitfields { - builder = builder.bitfield_enum(regex); - } - } - - if let Some(rustifieds) = matches.values_of("rustified-enum") { - for regex in rustifieds { - builder = builder.rustified_enum(regex); - } - } - - if let Some(constified_mods) = matches.values_of("constified-enum-module") { - for regex in constified_mods { - builder = builder.constified_enum_module(regex); - } - } - if let Some(hidden_types) = matches.values_of("blacklist-type") { - for ty in hidden_types { - builder = builder.blacklist_type(ty); - } - } - - if matches.is_present("builtins") { - builder = builder.emit_builtins(); - } - - if matches.is_present("no-layout-tests") { - builder = builder.layout_tests(false); - } - - if matches.is_present("no-derive-copy") { - builder = builder.derive_copy(false); - } - - if matches.is_present("no-derive-debug") { - builder = builder.derive_debug(false); - } - - if matches.is_present("impl-debug") { - builder = builder.impl_debug(true); - } - - if matches.is_present("impl-partialeq") { - builder = builder.impl_partialeq(true); - } - - if matches.is_present("with-derive-default") { - builder = builder.derive_default(true); - } - - if matches.is_present("with-derive-hash") { - builder = builder.derive_hash(true); - } - - if matches.is_present("with-derive-partialeq") { - builder = builder.derive_partialeq(true); - } - - if matches.is_present("with-derive-partialord") { - builder = builder.derive_partialord(true); - } - - if matches.is_present("with-derive-eq") { - builder = builder.derive_eq(true); - } - - if matches.is_present("with-derive-ord") { - builder = builder.derive_ord(true); - } - - if matches.is_present("no-derive-default") { - builder = builder.derive_default(false); - } - - if matches.is_present("no-prepend-enum-name") { - builder = builder.prepend_enum_name(false); - } - - if matches.is_present("time-phases") { - builder = builder.time_phases(true); - } - - if let Some(prefix) = matches.value_of("ctypes-prefix") { - builder = builder.ctypes_prefix(prefix); - } - - if let Some(what_to_generate) = matches.value_of("generate") { - let mut config = CodegenConfig::nothing(); - for what in what_to_generate.split(",") { - match what { - "functions" => config.functions = true, - "types" => config.types = true, - "vars" => config.vars = true, - "methods" => config.methods = true, - "constructors" => config.constructors = true, - "destructors" => config.destructors = true, - otherwise => { - return Err(Error::new( - ErrorKind::Other, - format!("Unknown generate item: {}", otherwise), - )); - } - } - } - builder = builder.with_codegen_config(config); - } - - if matches.is_present("emit-clang-ast") { - builder = builder.emit_clang_ast(); - } - - if matches.is_present("emit-ir") { - builder = builder.emit_ir(); - } - - if let Some(path) = matches.value_of("emit-ir-graphviz") { - builder = builder.emit_ir_graphviz(path); - } - - if matches.is_present("enable-cxx-namespaces") { - builder = builder.enable_cxx_namespaces(); - } - - if matches.is_present("disable-name-namespacing") { - builder = builder.disable_name_namespacing(); - } - - if matches.is_present("ignore-functions") { - builder = builder.ignore_functions(); - } - - if matches.is_present("ignore-methods") { - builder = builder.ignore_methods(); - } - - if matches.is_present("no-convert-floats") { - builder = builder.no_convert_floats(); - } - - if matches.is_present("no-doc-comments") { - builder = builder.generate_comments(false); - } - - if matches.is_present("no-recursive-whitelist") { - builder = builder.whitelist_recursively(false); - } - - if matches.is_present("objc-extern-crate") { - builder = builder.objc_extern_crate(true); - } - - if let Some(opaque_types) = matches.values_of("opaque-type") { - for ty in opaque_types { - builder = builder.opaque_type(ty); - } - } - - if let Some(lines) = matches.values_of("raw-line") { - for line in lines { - builder = builder.raw_line(line); - } - } - - if matches.is_present("use-core") { - builder = builder.use_core(); - } - - if matches.is_present("distrust-clang-mangling") { - builder = builder.trust_clang_mangling(false); - } - - if matches.is_present("conservative-inline-namespaces") { - builder = builder.conservative_inline_namespaces(); - } - - if matches.is_present("generate-inline-functions") { - builder = builder.generate_inline_functions(true); - } - - if let Some(whitelist) = matches.values_of("whitelist-function") { - for regex in whitelist { - builder = builder.whitelist_function(regex); - } - } - - if let Some(whitelist) = matches.values_of("whitelist-type") { - for regex in whitelist { - builder = builder.whitelist_type(regex); - } - } - - if let Some(whitelist) = matches.values_of("whitelist-var") { - for regex in whitelist { - builder = builder.whitelist_var(regex); - } - } - - if let Some(args) = matches.values_of("clang-args") { - for arg in args { - builder = builder.clang_arg(arg); - } - } - - let output = if let Some(path) = matches.value_of("output") { - let file = File::create(path)?; - Box::new(io::BufWriter::new(file)) as Box - } else { - Box::new(io::BufWriter::new(io::stdout())) as Box - }; - - if matches.is_present("dump-preprocessed-input") { - builder.dump_preprocessed_input()?; - } - - let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings"); - if no_rustfmt_bindings { - builder = builder.rustfmt_bindings(false); - } - - if let Some(path_str) = matches.value_of("rustfmt-configuration-file") { - let path = PathBuf::from(path_str); - - if no_rustfmt_bindings { - return Err(Error::new( - ErrorKind::Other, - "Cannot supply both --rustfmt-configuration-file and --no-rustfmt-bindings" - )); - } - - if !path.is_absolute() { - return Err(Error::new( - ErrorKind::Other, - "--rustfmt-configuration--file needs to be an absolute path!", - )); - } - - if path.to_str().is_none() { - return Err(Error::new( - ErrorKind::Other, - "--rustfmt-configuration-file contains non-valid UTF8 characters.", - )); - } - - builder = builder.rustfmt_configuration_file(Some(path)); - } - - if let Some(no_partialeq) = matches.values_of("no-partialeq") { - for regex in no_partialeq { - builder = builder.no_partialeq(regex); - } - } - - if let Some(no_copy) = matches.values_of("no-copy") { - for regex in no_copy { - builder = builder.no_copy(regex); - } - } - - if let Some(no_hash) = matches.values_of("no-hash") { - for regex in no_hash { - builder = builder.no_hash(regex); - } - } - - let verbose = matches.is_present("verbose"); - - Ok((builder, output, verbose)) -} diff --git a/src/parse.rs b/src/parse.rs deleted file mode 100644 index 1a9278b300..0000000000 --- a/src/parse.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! Common traits and types related to parsing our IR from Clang cursors. - -use clang; -use ir::context::{BindgenContext, ItemId, TypeId}; -use ir::ty::TypeKind; - -/// Not so much an error in the traditional sense, but a control flow message -/// when walking over Clang's AST with a cursor. -#[derive(Debug)] -pub enum ParseError { - /// Recurse down the current AST node's children. - Recurse, - /// Continue on to the next sibling AST node, or back up to the parent's - /// siblings if we've exhausted all of this node's siblings (and so on). - Continue, -} - -/// The result of parsing a Clang AST node. -#[derive(Debug)] -pub enum ParseResult { - /// We've already resolved this item before, here is the extant `ItemId` for - /// it. - AlreadyResolved(ItemId), - - /// This is a newly parsed item. If the cursor is `Some`, it points to the - /// AST node where the new `T` was declared. - New(T, Option), -} - -/// An intermediate representation "sub-item" (i.e. one of the types contained -/// inside an `ItemKind` variant) that can be parsed from a Clang cursor. -pub trait ClangSubItemParser: Sized { - /// Attempt to parse this type from the given cursor. - /// - /// The fact that is a reference guarantees it's held by the context, and - /// allow returning already existing types. - fn parse( - cursor: clang::Cursor, - context: &mut BindgenContext, - ) -> Result, ParseError>; -} - -/// An intermediate representation item that can be parsed from a Clang cursor. -pub trait ClangItemParser: Sized { - /// Parse this item from the given Clang cursor. - fn parse( - cursor: clang::Cursor, - parent: Option, - context: &mut BindgenContext, - ) -> Result; - - /// Parse this item from the given Clang type. - fn from_ty( - ty: &clang::Type, - location: clang::Cursor, - parent: Option, - ctx: &mut BindgenContext, - ) -> Result; - - /// Identical to `from_ty`, but use the given `id` as the `ItemId` for the - /// newly parsed item. - fn from_ty_with_id( - id: ItemId, - ty: &clang::Type, - location: clang::Cursor, - parent: Option, - ctx: &mut BindgenContext, - ) -> Result; - - /// Parse this item from the given Clang type, or if we haven't resolved all - /// the other items this one depends on, an unresolved reference. - fn from_ty_or_ref( - ty: clang::Type, - location: clang::Cursor, - parent_id: Option, - context: &mut BindgenContext, - ) -> TypeId; - - /// Identical to `from_ty_or_ref`, but use the given `potential_id` as the - /// `ItemId` for the newly parsed item. - fn from_ty_or_ref_with_id( - potential_id: ItemId, - ty: clang::Type, - location: clang::Cursor, - parent_id: Option, - context: &mut BindgenContext, - ) -> TypeId; - - /// Create a named template type. - fn type_param( - with_id: Option, - location: clang::Cursor, - ctx: &mut BindgenContext, - ) -> Option; - - /// Create a builtin type. - fn builtin_type( - kind: TypeKind, - is_const: bool, - context: &mut BindgenContext, - ) -> TypeId; -} diff --git a/src/regex_set.rs b/src/regex_set.rs deleted file mode 100644 index 8bd3ea7f61..0000000000 --- a/src/regex_set.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! A type that represents the union of a set of regular expressions. - -use regex::RegexSet as RxSet; - -// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex -// ORing all the patterns, I guess... - -/// A dynamic set of regular expressions. -#[derive(Debug)] -pub struct RegexSet { - items: Vec, - set: Option, -} - -impl RegexSet { - /// Is this set empty? - pub fn is_empty(&self) -> bool { - self.items.is_empty() - } - - /// Insert a new regex into this set. - pub fn insert(&mut self, string: S) - where - S: AsRef, - { - self.items.push(format!("^{}$", string.as_ref())); - self.set = None; - } - - /// Returns slice of String from its field 'items' - pub fn get_items(&self) -> &[String] { - &self.items[..] - } - - /// Construct a RegexSet from the set of entries we've accumulated. - /// - /// Must be called before calling `matches()`, or it will always return - /// false. - pub fn build(&mut self) { - self.set = match RxSet::new(&self.items) { - Ok(x) => Some(x), - Err(e) => { - error!("Invalid regex in {:?}: {:?}", self.items, e); - None - } - } - } - - /// Does the given `string` match any of the regexes in this set? - pub fn matches(&self, string: S) -> bool - where - S: AsRef, - { - let s = string.as_ref(); - self.set.as_ref().map(|set| set.is_match(s)).unwrap_or( - false, - ) - } -} - -impl Default for RegexSet { - fn default() -> Self { - RegexSet { - items: vec![], - set: None, - } - } -} diff --git a/src/time.rs b/src/time.rs deleted file mode 100644 index c841bccff4..0000000000 --- a/src/time.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::io::{self, Write}; -use std::time::{Instant, Duration}; - - -/// RAII timer to measure how long phases take. -#[derive(Debug)] -pub struct Timer<'a> { - output: bool, - name: &'a str, - start: Instant, -} - - -impl<'a> Timer<'a> { - /// Creates a Timer with the given name, and starts it. By default, - /// will print to stderr when it is `drop`'d - pub fn new(name: &'a str) -> Self { - Timer { - output: true, - name, - start: Instant::now() - } - } - - /// Sets whether or not the Timer will print a mesage - /// when it is dropped. - pub fn with_output(mut self, output: bool) -> Self { - self.output = output; - self - } - - /// Returns the time elapsed since the timer's creation - pub fn elapsed(&self) -> Duration { - Instant::now() - self.start - } - - fn print_elapsed(&mut self) { - if self.output { - let elapsed = self.elapsed(); - let time = (elapsed.as_secs() as f64) * 1e3 - + (elapsed.subsec_nanos() as f64) / 1e6; - let stderr = io::stderr(); - // Arbitrary output format, subject to change. - writeln!(stderr.lock(), - " time: {:>9.3} ms.\t{}", - time, self.name) - .expect("timer write should not fail"); - } - } -} - - -impl<'a> Drop for Timer<'a> { - fn drop(&mut self) { - self.print_elapsed(); - } -} diff --git a/tests/expectations/Cargo.toml b/tests/expectations/Cargo.toml deleted file mode 100644 index e0da6d5a96..0000000000 --- a/tests/expectations/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tests_expectations" -description = "bindgen results when ran on ../headers/*" -version = "0.1.0" -authors = [ - "Jyun-Yan You ", - "Emilio Cobos Álvarez ", - "The Servo project developers", -] - -[dependencies] -objc = "0.2" diff --git a/tests/expectations/build.rs b/tests/expectations/build.rs deleted file mode 100644 index 4f5e5a5ee6..0000000000 --- a/tests/expectations/build.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! Generate a module with a custom `#[path=...]` for each of the files in our -//! libclang version-specific test expectations so that they get their layout -//! tests run. We need to do this because cargo doesn't automatically detect -//! tests subdirectories. - -use std::env; -use std::fs; -use std::io::Write; -use std::path::Path; - -const LIBCLANG_VERSION_DIRS: &'static [&'static str] = - &["libclang-3.8", "libclang-3.9", "libclang-4", "libclang-5"]; - -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - - let mut test_string = String::new(); - - for dir in LIBCLANG_VERSION_DIRS { - let dir = Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()) - .join("tests") - .join(dir); - - println!("cargo:rerun-if-changed={}", dir.display()); - - for entry in fs::read_dir(dir).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - let path = path.canonicalize().unwrap_or_else(|_| path.into()); - if path.extension().map(|e| e.to_string_lossy()) != Some("rs".into()) { - continue; - } - - println!("cargo:rerun-if-changed={}", path.display()); - - let module_name: String = path.display() - .to_string() - .chars() - .map(|c| match c { - 'a'...'z' | 'A'...'Z' | '0'...'9' => c, - _ => '_', - }) - .collect(); - - test_string.push_str(&format!( - r###" -#[path = "{}"] -mod {}; -"###, - path.display(), - module_name, - )); - } - } - - let out_path = Path::new(&env::var_os("OUT_DIR").unwrap()) - .join("libclang_version_specific_generated_tests.rs"); - let mut test_file = fs::File::create(out_path).unwrap(); - test_file.write_all(test_string.as_bytes()).unwrap(); -} diff --git a/tests/expectations/lib.rs b/tests/expectations/lib.rs deleted file mode 100755 index 562dc5548d..0000000000 --- a/tests/expectations/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![allow(dead_code)] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] diff --git a/tests/expectations/tests/16-byte-alignment.rs b/tests/expectations/tests/16-byte-alignment.rs deleted file mode 100644 index 84383c3575..0000000000 --- a/tests/expectations/tests/16-byte-alignment.rs +++ /dev/null @@ -1,312 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_ipv4_tuple { - pub src_addr: u32, - pub dst_addr: u32, - pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_ipv4_tuple__bindgen_ty_1 { - pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1, - pub sctp_tag: u32, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1 { - pub dport: u16, - pub sport: u16, -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dport as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(dport) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sport as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(sport) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ipv4_tuple__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv4_tuple__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sctp_tag as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1), - "::", - stringify!(sctp_tag) - ) - ); -} -impl Default for rte_ipv4_tuple__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_ipv4_tuple)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv4_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple), - "::", - stringify!(src_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_addr as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple), - "::", - stringify!(dst_addr) - ) - ); -} -impl Default for rte_ipv4_tuple { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_ipv6_tuple { - pub src_addr: [u8; 16usize], - pub dst_addr: [u8; 16usize], - pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_ipv6_tuple__bindgen_ty_1 { - pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1, - pub sctp_tag: u32, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1 { - pub dport: u16, - pub sport: u16, -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dport as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(dport) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sport as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(sport) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ipv6_tuple__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv6_tuple__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sctp_tag as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1), - "::", - stringify!(sctp_tag) - ) - ); -} -impl Default for rte_ipv6_tuple__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_ipv6_tuple)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv6_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple), - "::", - stringify!(src_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_addr as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple), - "::", - stringify!(dst_addr) - ) - ); -} -impl Default for rte_ipv6_tuple { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_thash_tuple { - pub v4: rte_ipv4_tuple, - pub v6: rte_ipv6_tuple, - _bindgen_union_align: [u8; 48usize], -} -#[test] -fn bindgen_test_layout_rte_thash_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(rte_thash_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).v4 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_thash_tuple), - "::", - stringify!(v4) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).v6 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_thash_tuple), - "::", - stringify!(v6) - ) - ); -} -impl Default for rte_thash_tuple { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/16-byte-alignment_1_0.rs b/tests/expectations/tests/16-byte-alignment_1_0.rs deleted file mode 100644 index f37721a49b..0000000000 --- a/tests/expectations/tests/16-byte-alignment_1_0.rs +++ /dev/null @@ -1,370 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv4_tuple { - pub src_addr: u32, - pub dst_addr: u32, - pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv4_tuple__bindgen_ty_1 { - pub __bindgen_anon_1: __BindgenUnionField, - pub sctp_tag: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1 { - pub dport: u16, - pub sport: u16, -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dport as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(dport) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sport as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(sport) - ) - ); -} -impl Clone for rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ipv4_tuple__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv4_tuple__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sctp_tag as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple__bindgen_ty_1), - "::", - stringify!(sctp_tag) - ) - ); -} -impl Clone for rte_ipv4_tuple__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_ipv4_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_ipv4_tuple)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv4_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple), - "::", - stringify!(src_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_addr as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv4_tuple), - "::", - stringify!(dst_addr) - ) - ); -} -impl Clone for rte_ipv4_tuple { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv6_tuple { - pub src_addr: [u8; 16usize], - pub dst_addr: [u8; 16usize], - pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv6_tuple__bindgen_ty_1 { - pub __bindgen_anon_1: __BindgenUnionField, - pub sctp_tag: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1 { - pub dport: u16, - pub sport: u16, -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dport as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(dport) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sport as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(sport) - ) - ); -} -impl Clone for rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ipv6_tuple__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv6_tuple__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).sctp_tag as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple__bindgen_ty_1), - "::", - stringify!(sctp_tag) - ) - ); -} -impl Clone for rte_ipv6_tuple__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_ipv6_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_ipv6_tuple)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ipv6_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple), - "::", - stringify!(src_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_addr as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_ipv6_tuple), - "::", - stringify!(dst_addr) - ) - ); -} -impl Clone for rte_ipv6_tuple { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Copy)] -pub struct rte_thash_tuple { - pub v4: __BindgenUnionField, - pub v6: __BindgenUnionField, - pub bindgen_union_field: [u8; 48usize], -} -#[test] -fn bindgen_test_layout_rte_thash_tuple() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(rte_thash_tuple)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).v4 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_thash_tuple), - "::", - stringify!(v4) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).v6 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_thash_tuple), - "::", - stringify!(v6) - ) - ); -} -impl Clone for rte_thash_tuple { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_thash_tuple { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/accessors.rs b/tests/expectations/tests/accessors.rs deleted file mode 100644 index 43422ac5b9..0000000000 --- a/tests/expectations/tests/accessors.rs +++ /dev/null @@ -1,387 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct SomeAccessors { - pub mNoAccessor: ::std::os::raw::c_int, - ///
- pub mBothAccessors: ::std::os::raw::c_int, - ///
- pub mUnsafeAccessors: ::std::os::raw::c_int, - ///
- pub mImmutableAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_SomeAccessors() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(SomeAccessors)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(SomeAccessors)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mNoAccessor as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(SomeAccessors), - "::", - stringify!(mNoAccessor) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBothAccessors as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(SomeAccessors), - "::", - stringify!(mBothAccessors) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mUnsafeAccessors as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(SomeAccessors), - "::", - stringify!(mUnsafeAccessors) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mImmutableAccessor as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(SomeAccessors), - "::", - stringify!(mImmutableAccessor) - ) - ); -} -impl SomeAccessors { - #[inline] - pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mBothAccessors - } - #[inline] - pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mBothAccessors - } - #[inline] - pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int { - &self.mUnsafeAccessors - } - #[inline] - pub unsafe fn get_mUnsafeAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mUnsafeAccessors - } - #[inline] - pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { - &self.mImmutableAccessor - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct AllAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - pub mAlsoBothAccessors: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_AllAccessors() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(AllAccessors)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(AllAccessors)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBothAccessors as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(AllAccessors), - "::", - stringify!(mBothAccessors) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mAlsoBothAccessors as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(AllAccessors), - "::", - stringify!(mAlsoBothAccessors) - ) - ); -} -impl AllAccessors { - #[inline] - pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mBothAccessors - } - #[inline] - pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mBothAccessors - } - #[inline] - pub fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mAlsoBothAccessors - } - #[inline] - pub fn get_mAlsoBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mAlsoBothAccessors - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct AllUnsafeAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - pub mAlsoBothAccessors: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_AllUnsafeAccessors() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(AllUnsafeAccessors)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(AllUnsafeAccessors)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mBothAccessors as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(AllUnsafeAccessors), - "::", - stringify!(mBothAccessors) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mAlsoBothAccessors as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(AllUnsafeAccessors), - "::", - stringify!(mAlsoBothAccessors) - ) - ); -} -impl AllUnsafeAccessors { - #[inline] - pub unsafe fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mBothAccessors - } - #[inline] - pub unsafe fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mBothAccessors - } - #[inline] - pub unsafe fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mAlsoBothAccessors - } - #[inline] - pub unsafe fn get_mAlsoBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mAlsoBothAccessors - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct ContradictAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - ///
- pub mNoAccessors: ::std::os::raw::c_int, - ///
- pub mUnsafeAccessors: ::std::os::raw::c_int, - ///
- pub mImmutableAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContradictAccessors() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ContradictAccessors)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContradictAccessors)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mBothAccessors as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContradictAccessors), - "::", - stringify!(mBothAccessors) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mNoAccessors as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ContradictAccessors), - "::", - stringify!(mNoAccessors) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mUnsafeAccessors as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ContradictAccessors), - "::", - stringify!(mUnsafeAccessors) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mImmutableAccessor as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(ContradictAccessors), - "::", - stringify!(mImmutableAccessor) - ) - ); -} -impl ContradictAccessors { - #[inline] - pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int { - &self.mBothAccessors - } - #[inline] - pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mBothAccessors - } - #[inline] - pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int { - &self.mUnsafeAccessors - } - #[inline] - pub unsafe fn get_mUnsafeAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mUnsafeAccessors - } - #[inline] - pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { - &self.mImmutableAccessor - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Replaced { - pub mAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Replaced() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Replaced)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Replaced)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mAccessor as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Replaced), - "::", - stringify!(mAccessor) - ) - ); -} -impl Replaced { - #[inline] - pub fn get_mAccessor(&self) -> &::std::os::raw::c_int { - &self.mAccessor - } - #[inline] - pub fn get_mAccessor_mut(&mut self) -> &mut ::std::os::raw::c_int { - &mut self.mAccessor - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Wrapper { - pub mReplaced: Replaced, -} -#[test] -fn bindgen_test_layout_Wrapper() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Wrapper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Wrapper)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mReplaced as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Wrapper), - "::", - stringify!(mReplaced) - ) - ); -} -impl Wrapper { - #[inline] - pub fn get_mReplaced(&self) -> &Replaced { - &self.mReplaced - } - #[inline] - pub fn get_mReplaced_mut(&mut self) -> &mut Replaced { - &mut self.mReplaced - } -} diff --git a/tests/expectations/tests/annotation_hide.rs b/tests/expectations/tests/annotation_hide.rs deleted file mode 100644 index 6657a9502d..0000000000 --- a/tests/expectations/tests/annotation_hide.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct D { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(D)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(D)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NotAnnotated { - pub f: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NotAnnotated() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NotAnnotated)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NotAnnotated)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NotAnnotated), - "::", - stringify!(f) - ) - ); -} diff --git a/tests/expectations/tests/anon_enum.rs b/tests/expectations/tests/anon_enum.rs deleted file mode 100644 index 76d6089f90..0000000000 --- a/tests/expectations/tests/anon_enum.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct Test { - pub foo: ::std::os::raw::c_int, - pub bar: f32, -} -pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Test__bindgen_ty_1 { - T_NONE = 0, -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(bar)) - ); -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Baz { - Foo = 0, - Bar = 1, -} diff --git a/tests/expectations/tests/anon_enum_trait.rs b/tests/expectations/tests/anon_enum_trait.rs deleted file mode 100644 index 6eb9f4407e..0000000000 --- a/tests/expectations/tests/anon_enum_trait.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct DataType { - pub _address: u8, -} -pub type DataType_value_type<_Tp> = _Tp; -pub type DataType_work_type<_Tp> = DataType_value_type<_Tp>; -pub type DataType_channel_type<_Tp> = DataType_value_type<_Tp>; -pub type DataType_vec_type<_Tp> = DataType_value_type<_Tp>; -pub const DataType_generic_type: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; -pub const DataType_depth: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; -pub const DataType_channels: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; -pub const DataType_fmt: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; -pub const DataType_type_: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum DataType__bindgen_ty_1 { - generic_type = 0, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_Bar: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar; -pub const Foo_Baz: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo__bindgen_ty_1 { - Bar = 0, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/anon_enum_whitelist.rs b/tests/expectations/tests/anon_enum_whitelist.rs deleted file mode 100644 index 267d922961..0000000000 --- a/tests/expectations/tests/anon_enum_whitelist.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO; -pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - NODE_FLAG_FOO = 0, - NODE_FLAG_BAR = 1, -} diff --git a/tests/expectations/tests/anon_struct_in_union.rs b/tests/expectations/tests/anon_struct_in_union.rs deleted file mode 100644 index 6916d5afe8..0000000000 --- a/tests/expectations/tests/anon_struct_in_union.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct s { - pub u: s__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union s__bindgen_ty_1 { - pub field: s__bindgen_ty_1_inner, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct s__bindgen_ty_1_inner { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_s__bindgen_ty_1_inner() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s__bindgen_ty_1_inner)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s__bindgen_ty_1_inner)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(s__bindgen_ty_1_inner), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_s__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).field as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(s__bindgen_ty_1), - "::", - stringify!(field) - ) - ); -} -impl Default for s__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_s() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(s), "::", stringify!(u)) - ); -} -impl Default for s { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/anon_struct_in_union_1_0.rs b/tests/expectations/tests/anon_struct_in_union_1_0.rs deleted file mode 100644 index 63e2e45a75..0000000000 --- a/tests/expectations/tests/anon_struct_in_union_1_0.rs +++ /dev/null @@ -1,144 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct s { - pub u: s__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct s__bindgen_ty_1 { - pub field: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct s__bindgen_ty_1_inner { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_s__bindgen_ty_1_inner() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s__bindgen_ty_1_inner)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s__bindgen_ty_1_inner)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(s__bindgen_ty_1_inner), - "::", - stringify!(b) - ) - ); -} -impl Clone for s__bindgen_ty_1_inner { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_s__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).field as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(s__bindgen_ty_1), - "::", - stringify!(field) - ) - ); -} -impl Clone for s__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_s() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(s)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(s)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(s), "::", stringify!(u)) - ); -} -impl Clone for s { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/anon_union.rs b/tests/expectations/tests/anon_union.rs deleted file mode 100644 index 446cd58962..0000000000 --- a/tests/expectations/tests/anon_union.rs +++ /dev/null @@ -1,85 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct TErrorResult { - pub mResult: ::std::os::raw::c_int, - pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, - pub mMightHaveUnreported: bool, - pub mUnionState: TErrorResult_UnionState, -} -pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState = - TErrorResult_UnionState::HasMessage; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum TErrorResult_UnionState { - HasMessage = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult_Message { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult_DOMExceptionInfo { - _unused: [u8; 0], -} -#[repr(C)] -pub union TErrorResult__bindgen_ty_1 { - pub mMessage: *mut TErrorResult_Message, - pub mDOMExceptionInfo: *mut TErrorResult_DOMExceptionInfo, - _bindgen_union_align: u64, -} -impl Default for TErrorResult__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for TErrorResult { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct ErrorResult { - pub _base: TErrorResult, -} -#[test] -fn bindgen_test_layout_ErrorResult() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(ErrorResult)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ErrorResult)) - ); -} -impl Default for ErrorResult { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_TErrorResult_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(TErrorResult) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(TErrorResult) - ) - ); -} diff --git a/tests/expectations/tests/anon_union_1_0.rs b/tests/expectations/tests/anon_union_1_0.rs deleted file mode 100644 index 60e2e0c5cc..0000000000 --- a/tests/expectations/tests/anon_union_1_0.rs +++ /dev/null @@ -1,131 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct TErrorResult { - pub mResult: ::std::os::raw::c_int, - pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, - pub mMightHaveUnreported: bool, - pub mUnionState: TErrorResult_UnionState, -} -pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState = - TErrorResult_UnionState::HasMessage; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum TErrorResult_UnionState { - HasMessage = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult_Message { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult_DOMExceptionInfo { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct TErrorResult__bindgen_ty_1 { - pub mMessage: __BindgenUnionField<*mut TErrorResult_Message>, - pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo>, - pub bindgen_union_field: u64, -} -impl Default for TErrorResult { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct ErrorResult { - pub _base: TErrorResult, -} -#[test] -fn bindgen_test_layout_ErrorResult() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(ErrorResult)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ErrorResult)) - ); -} -impl Clone for ErrorResult { - fn clone(&self) -> Self { - *self - } -} -impl Default for ErrorResult { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_TErrorResult_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(TErrorResult) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(TErrorResult) - ) - ); -} diff --git a/tests/expectations/tests/anonymous-template-types.rs b/tests/expectations/tests/anonymous-template-types.rs deleted file mode 100644 index 0fedfe4532..0000000000 --- a/tests/expectations/tests/anonymous-template-types.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Foo { - pub t_member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Bar { - pub member: ::std::os::raw::c_char, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Quux { - pub v_member: V, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Quux { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Lobo { - pub also_member: ::std::os::raw::c_char, -} -pub type AliasWithAnonType = ::std::os::raw::c_char; diff --git a/tests/expectations/tests/arg_keyword.rs b/tests/expectations/tests/arg_keyword.rs deleted file mode 100644 index 54c036d886..0000000000 --- a/tests/expectations/tests/arg_keyword.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_Z3fooPKc"] - pub fn foo(type_: *const ::std::os::raw::c_char); -} diff --git a/tests/expectations/tests/array-of-zero-sized-types.rs b/tests/expectations/tests/array-of-zero-sized-types.rs deleted file mode 100644 index 6e6193c98e..0000000000 --- a/tests/expectations/tests/array-of-zero-sized-types.rs +++ /dev/null @@ -1,56 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This should get an `_address` byte. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Empty { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Empty() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Empty)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Empty)) - ); -} -/// This should not get an `_address` byte, since each `Empty` gets one, meaning -/// that this object is addressable. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct HasArrayOfEmpty { - pub empties: [Empty; 10usize], -} -#[test] -fn bindgen_test_layout_HasArrayOfEmpty() { - assert_eq!( - ::std::mem::size_of::(), - 10usize, - concat!("Size of: ", stringify!(HasArrayOfEmpty)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(HasArrayOfEmpty)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).empties as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(HasArrayOfEmpty), - "::", - stringify!(empties) - ) - ); -} diff --git a/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs b/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs deleted file mode 100644 index 901bec60d2..0000000000 --- a/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct std_char_traits { - pub _address: u8, -} -impl Default for std_char_traits { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct __gnu_cxx_char_traits { - pub _address: u8, -} diff --git a/tests/expectations/tests/base-to-derived.rs b/tests/expectations/tests/base-to-derived.rs deleted file mode 100644 index 9df54d982e..0000000000 --- a/tests/expectations/tests/base-to-derived.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct false_type { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_false_type() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(false_type)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(false_type)) - ); -} diff --git a/tests/expectations/tests/bitfield-32bit-overflow.rs b/tests/expectations/tests/bitfield-32bit-overflow.rs deleted file mode 100644 index f64299a6ab..0000000000 --- a/tests/expectations/tests/bitfield-32bit-overflow.rs +++ /dev/null @@ -1,640 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct MuchBitfield { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize], u8>, -} -#[test] -fn bindgen_test_layout_MuchBitfield() { - assert_eq!( - ::std::mem::size_of::(), - 5usize, - concat!("Size of: ", stringify!(MuchBitfield)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(MuchBitfield)) - ); -} -impl MuchBitfield { - #[inline] - pub fn m0(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_m0(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn m1(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } - } - #[inline] - pub fn set_m1(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn m2(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } - } - #[inline] - pub fn set_m2(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn m3(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) } - } - #[inline] - pub fn set_m3(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 1u8, val as u64) - } - } - #[inline] - pub fn m4(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) } - } - #[inline] - pub fn set_m4(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 1u8, val as u64) - } - } - #[inline] - pub fn m5(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) } - } - #[inline] - pub fn set_m5(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(5usize, 1u8, val as u64) - } - } - #[inline] - pub fn m6(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) } - } - #[inline] - pub fn set_m6(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn m7(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) } - } - #[inline] - pub fn set_m7(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn m8(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u8) } - } - #[inline] - pub fn set_m8(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn m9(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u8) } - } - #[inline] - pub fn set_m9(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 1u8, val as u64) - } - } - #[inline] - pub fn m10(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u8) } - } - #[inline] - pub fn set_m10(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(10usize, 1u8, val as u64) - } - } - #[inline] - pub fn m11(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u8) } - } - #[inline] - pub fn set_m11(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(11usize, 1u8, val as u64) - } - } - #[inline] - pub fn m12(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u8) } - } - #[inline] - pub fn set_m12(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(12usize, 1u8, val as u64) - } - } - #[inline] - pub fn m13(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u8) } - } - #[inline] - pub fn set_m13(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(13usize, 1u8, val as u64) - } - } - #[inline] - pub fn m14(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u8) } - } - #[inline] - pub fn set_m14(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(14usize, 1u8, val as u64) - } - } - #[inline] - pub fn m15(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u8) } - } - #[inline] - pub fn set_m15(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(15usize, 1u8, val as u64) - } - } - #[inline] - pub fn m16(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 1u8) as u8) } - } - #[inline] - pub fn set_m16(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 1u8, val as u64) - } - } - #[inline] - pub fn m17(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(17usize, 1u8) as u8) } - } - #[inline] - pub fn set_m17(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(17usize, 1u8, val as u64) - } - } - #[inline] - pub fn m18(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(18usize, 1u8) as u8) } - } - #[inline] - pub fn set_m18(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(18usize, 1u8, val as u64) - } - } - #[inline] - pub fn m19(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 1u8) as u8) } - } - #[inline] - pub fn set_m19(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(19usize, 1u8, val as u64) - } - } - #[inline] - pub fn m20(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 1u8) as u8) } - } - #[inline] - pub fn set_m20(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(20usize, 1u8, val as u64) - } - } - #[inline] - pub fn m21(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 1u8) as u8) } - } - #[inline] - pub fn set_m21(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(21usize, 1u8, val as u64) - } - } - #[inline] - pub fn m22(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(22usize, 1u8) as u8) } - } - #[inline] - pub fn set_m22(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(22usize, 1u8, val as u64) - } - } - #[inline] - pub fn m23(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(23usize, 1u8) as u8) } - } - #[inline] - pub fn set_m23(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(23usize, 1u8, val as u64) - } - } - #[inline] - pub fn m24(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 1u8) as u8) } - } - #[inline] - pub fn set_m24(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 1u8, val as u64) - } - } - #[inline] - pub fn m25(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(25usize, 1u8) as u8) } - } - #[inline] - pub fn set_m25(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(25usize, 1u8, val as u64) - } - } - #[inline] - pub fn m26(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(26usize, 1u8) as u8) } - } - #[inline] - pub fn set_m26(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(26usize, 1u8, val as u64) - } - } - #[inline] - pub fn m27(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(27usize, 1u8) as u8) } - } - #[inline] - pub fn set_m27(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(27usize, 1u8, val as u64) - } - } - #[inline] - pub fn m28(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 1u8) as u8) } - } - #[inline] - pub fn set_m28(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(28usize, 1u8, val as u64) - } - } - #[inline] - pub fn m29(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u8) } - } - #[inline] - pub fn set_m29(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(29usize, 1u8, val as u64) - } - } - #[inline] - pub fn m30(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u8) } - } - #[inline] - pub fn set_m30(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(30usize, 1u8, val as u64) - } - } - #[inline] - pub fn m31(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } - } - #[inline] - pub fn set_m31(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(31usize, 1u8, val as u64) - } - } - #[inline] - pub fn m32(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 1u8) as u8) } - } - #[inline] - pub fn set_m32(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(32usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - m0: ::std::os::raw::c_char, - m1: ::std::os::raw::c_char, - m2: ::std::os::raw::c_char, - m3: ::std::os::raw::c_char, - m4: ::std::os::raw::c_char, - m5: ::std::os::raw::c_char, - m6: ::std::os::raw::c_char, - m7: ::std::os::raw::c_char, - m8: ::std::os::raw::c_char, - m9: ::std::os::raw::c_char, - m10: ::std::os::raw::c_char, - m11: ::std::os::raw::c_char, - m12: ::std::os::raw::c_char, - m13: ::std::os::raw::c_char, - m14: ::std::os::raw::c_char, - m15: ::std::os::raw::c_char, - m16: ::std::os::raw::c_char, - m17: ::std::os::raw::c_char, - m18: ::std::os::raw::c_char, - m19: ::std::os::raw::c_char, - m20: ::std::os::raw::c_char, - m21: ::std::os::raw::c_char, - m22: ::std::os::raw::c_char, - m23: ::std::os::raw::c_char, - m24: ::std::os::raw::c_char, - m25: ::std::os::raw::c_char, - m26: ::std::os::raw::c_char, - m27: ::std::os::raw::c_char, - m28: ::std::os::raw::c_char, - m29: ::std::os::raw::c_char, - m30: ::std::os::raw::c_char, - m31: ::std::os::raw::c_char, - m32: ::std::os::raw::c_char, - ) -> __BindgenBitfieldUnit<[u8; 5usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 5usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let m0: u8 = unsafe { ::std::mem::transmute(m0) }; - m0 as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let m1: u8 = unsafe { ::std::mem::transmute(m1) }; - m1 as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let m2: u8 = unsafe { ::std::mem::transmute(m2) }; - m2 as u64 - }); - __bindgen_bitfield_unit.set(3usize, 1u8, { - let m3: u8 = unsafe { ::std::mem::transmute(m3) }; - m3 as u64 - }); - __bindgen_bitfield_unit.set(4usize, 1u8, { - let m4: u8 = unsafe { ::std::mem::transmute(m4) }; - m4 as u64 - }); - __bindgen_bitfield_unit.set(5usize, 1u8, { - let m5: u8 = unsafe { ::std::mem::transmute(m5) }; - m5 as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let m6: u8 = unsafe { ::std::mem::transmute(m6) }; - m6 as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let m7: u8 = unsafe { ::std::mem::transmute(m7) }; - m7 as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let m8: u8 = unsafe { ::std::mem::transmute(m8) }; - m8 as u64 - }); - __bindgen_bitfield_unit.set(9usize, 1u8, { - let m9: u8 = unsafe { ::std::mem::transmute(m9) }; - m9 as u64 - }); - __bindgen_bitfield_unit.set(10usize, 1u8, { - let m10: u8 = unsafe { ::std::mem::transmute(m10) }; - m10 as u64 - }); - __bindgen_bitfield_unit.set(11usize, 1u8, { - let m11: u8 = unsafe { ::std::mem::transmute(m11) }; - m11 as u64 - }); - __bindgen_bitfield_unit.set(12usize, 1u8, { - let m12: u8 = unsafe { ::std::mem::transmute(m12) }; - m12 as u64 - }); - __bindgen_bitfield_unit.set(13usize, 1u8, { - let m13: u8 = unsafe { ::std::mem::transmute(m13) }; - m13 as u64 - }); - __bindgen_bitfield_unit.set(14usize, 1u8, { - let m14: u8 = unsafe { ::std::mem::transmute(m14) }; - m14 as u64 - }); - __bindgen_bitfield_unit.set(15usize, 1u8, { - let m15: u8 = unsafe { ::std::mem::transmute(m15) }; - m15 as u64 - }); - __bindgen_bitfield_unit.set(16usize, 1u8, { - let m16: u8 = unsafe { ::std::mem::transmute(m16) }; - m16 as u64 - }); - __bindgen_bitfield_unit.set(17usize, 1u8, { - let m17: u8 = unsafe { ::std::mem::transmute(m17) }; - m17 as u64 - }); - __bindgen_bitfield_unit.set(18usize, 1u8, { - let m18: u8 = unsafe { ::std::mem::transmute(m18) }; - m18 as u64 - }); - __bindgen_bitfield_unit.set(19usize, 1u8, { - let m19: u8 = unsafe { ::std::mem::transmute(m19) }; - m19 as u64 - }); - __bindgen_bitfield_unit.set(20usize, 1u8, { - let m20: u8 = unsafe { ::std::mem::transmute(m20) }; - m20 as u64 - }); - __bindgen_bitfield_unit.set(21usize, 1u8, { - let m21: u8 = unsafe { ::std::mem::transmute(m21) }; - m21 as u64 - }); - __bindgen_bitfield_unit.set(22usize, 1u8, { - let m22: u8 = unsafe { ::std::mem::transmute(m22) }; - m22 as u64 - }); - __bindgen_bitfield_unit.set(23usize, 1u8, { - let m23: u8 = unsafe { ::std::mem::transmute(m23) }; - m23 as u64 - }); - __bindgen_bitfield_unit.set(24usize, 1u8, { - let m24: u8 = unsafe { ::std::mem::transmute(m24) }; - m24 as u64 - }); - __bindgen_bitfield_unit.set(25usize, 1u8, { - let m25: u8 = unsafe { ::std::mem::transmute(m25) }; - m25 as u64 - }); - __bindgen_bitfield_unit.set(26usize, 1u8, { - let m26: u8 = unsafe { ::std::mem::transmute(m26) }; - m26 as u64 - }); - __bindgen_bitfield_unit.set(27usize, 1u8, { - let m27: u8 = unsafe { ::std::mem::transmute(m27) }; - m27 as u64 - }); - __bindgen_bitfield_unit.set(28usize, 1u8, { - let m28: u8 = unsafe { ::std::mem::transmute(m28) }; - m28 as u64 - }); - __bindgen_bitfield_unit.set(29usize, 1u8, { - let m29: u8 = unsafe { ::std::mem::transmute(m29) }; - m29 as u64 - }); - __bindgen_bitfield_unit.set(30usize, 1u8, { - let m30: u8 = unsafe { ::std::mem::transmute(m30) }; - m30 as u64 - }); - __bindgen_bitfield_unit.set(31usize, 1u8, { - let m31: u8 = unsafe { ::std::mem::transmute(m31) }; - m31 as u64 - }); - __bindgen_bitfield_unit.set(32usize, 1u8, { - let m32: u8 = unsafe { ::std::mem::transmute(m32) }; - m32 as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/bitfield-large.rs b/tests/expectations/tests/bitfield-large.rs deleted file mode 100644 index 7b93f1190b..0000000000 --- a/tests/expectations/tests/bitfield-large.rs +++ /dev/null @@ -1,111 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct HasBigBitfield { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>, -} -#[test] -fn bindgen_test_layout_HasBigBitfield() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(HasBigBitfield)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct HasTwoBigBitfields { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>, -} -#[test] -fn bindgen_test_layout_HasTwoBigBitfields() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(HasTwoBigBitfields)) - ); -} diff --git a/tests/expectations/tests/bitfield-method-same-name.rs b/tests/expectations/tests/bitfield-method-same-name.rs deleted file mode 100644 index b8700605a4..0000000000 --- a/tests/expectations/tests/bitfield-method-same-name.rs +++ /dev/null @@ -1,153 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4typeEv"] - pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo9set_type_Ec"] - pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_char); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo8set_typeEc"] - pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_char); -} -impl Foo { - #[inline] - pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u8) } - } - #[inline] - pub fn set_type__bindgen_bitfield(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - type__bindgen_bitfield: ::std::os::raw::c_char, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let type__bindgen_bitfield: u8 = - unsafe { ::std::mem::transmute(type__bindgen_bitfield) }; - type__bindgen_bitfield as u64 - }); - __bindgen_bitfield_unit - } - #[inline] - pub unsafe fn type_(&mut self) -> ::std::os::raw::c_char { - Foo_type(self) - } - #[inline] - pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_char) { - Foo_set_type_(self, c) - } - #[inline] - pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_char) { - Foo_set_type(self, c) - } -} diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs deleted file mode 100644 index d7ee04456d..0000000000 --- a/tests/expectations/tests/bitfield_align.rs +++ /dev/null @@ -1,720 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub x: ::std::os::raw::c_uchar, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, - pub y: ::std::os::raw::c_uchar, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::
(), - 4usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(x)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).y as *const _ as usize }, - 3usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(y)) - ); -} -impl A { - #[inline] - pub fn b1(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } - } - #[inline] - pub fn set_b1(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b2(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } - } - #[inline] - pub fn set_b2(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn b3(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } - } - #[inline] - pub fn set_b3(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn b4(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } - } - #[inline] - pub fn set_b4(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 1u8, val as u64) - } - } - #[inline] - pub fn b5(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) } - } - #[inline] - pub fn set_b5(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 1u8, val as u64) - } - } - #[inline] - pub fn b6(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) } - } - #[inline] - pub fn set_b6(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(5usize, 1u8, val as u64) - } - } - #[inline] - pub fn b7(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) } - } - #[inline] - pub fn set_b7(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn b8(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) } - } - #[inline] - pub fn set_b8(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn b9(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) } - } - #[inline] - pub fn set_b9(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn b10(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) } - } - #[inline] - pub fn set_b10(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - b1: ::std::os::raw::c_uint, - b2: ::std::os::raw::c_uint, - b3: ::std::os::raw::c_uint, - b4: ::std::os::raw::c_uint, - b5: ::std::os::raw::c_uint, - b6: ::std::os::raw::c_uint, - b7: ::std::os::raw::c_uint, - b8: ::std::os::raw::c_uint, - b9: ::std::os::raw::c_uint, - b10: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let b1: u32 = unsafe { ::std::mem::transmute(b1) }; - b1 as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let b2: u32 = unsafe { ::std::mem::transmute(b2) }; - b2 as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let b3: u32 = unsafe { ::std::mem::transmute(b3) }; - b3 as u64 - }); - __bindgen_bitfield_unit.set(3usize, 1u8, { - let b4: u32 = unsafe { ::std::mem::transmute(b4) }; - b4 as u64 - }); - __bindgen_bitfield_unit.set(4usize, 1u8, { - let b5: u32 = unsafe { ::std::mem::transmute(b5) }; - b5 as u64 - }); - __bindgen_bitfield_unit.set(5usize, 1u8, { - let b6: u32 = unsafe { ::std::mem::transmute(b6) }; - b6 as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let b7: u32 = unsafe { ::std::mem::transmute(b7) }; - b7 as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let b8: u32 = unsafe { ::std::mem::transmute(b8) }; - b8 as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let b9: u32 = unsafe { ::std::mem::transmute(b9) }; - b9 as u64 - }); - __bindgen_bitfield_unit.set(9usize, 1u8, { - let b10: u32 = unsafe { ::std::mem::transmute(b10) }; - b10 as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct B { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B)) - ); -} -impl B { - #[inline] - pub fn foo(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 31u8) as u32) } - } - #[inline] - pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 31u8, val as u64) - } - } - #[inline] - pub fn bar(&self) -> ::std::os::raw::c_uchar { - unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } - } - #[inline] - pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(31usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - foo: ::std::os::raw::c_uint, - bar: ::std::os::raw::c_uchar, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 31u8, { - let foo: u32 = unsafe { ::std::mem::transmute(foo) }; - foo as u64 - }); - __bindgen_bitfield_unit.set(31usize, 1u8, { - let bar: u8 = unsafe { ::std::mem::transmute(bar) }; - bar as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct C { - pub x: ::std::os::raw::c_uchar, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub baz: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(x)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(baz)) - ); -} -impl C { - #[inline] - pub fn b1(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } - } - #[inline] - pub fn set_b1(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b2(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } - } - #[inline] - pub fn set_b2(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - b1: ::std::os::raw::c_uint, - b2: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let b1: u32 = unsafe { ::std::mem::transmute(b1) }; - b1 as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let b2: u32 = unsafe { ::std::mem::transmute(b2) }; - b2 as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Date1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize], u8>, - pub __bindgen_padding_0: u8, - pub __bindgen_align: [u16; 0usize], -} -#[test] -fn bindgen_test_layout_Date1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Date1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(Date1)) - ); -} -impl Date1 { - #[inline] - pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } - } - #[inline] - pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } - } - #[inline] - pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 6u8, val as u64) - } - } - #[inline] - pub fn nMonth(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } - } - #[inline] - pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 5u8, val as u64) - } - } - #[inline] - pub fn nYear(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } - } - #[inline] - pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 8u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - nWeekDay: ::std::os::raw::c_ushort, - nMonthDay: ::std::os::raw::c_ushort, - nMonth: ::std::os::raw::c_ushort, - nYear: ::std::os::raw::c_ushort, - ) -> __BindgenBitfieldUnit<[u8; 3usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; - nWeekDay as u64 - }); - __bindgen_bitfield_unit.set(3usize, 6u8, { - let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; - nMonthDay as u64 - }); - __bindgen_bitfield_unit.set(9usize, 5u8, { - let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; - nMonth as u64 - }); - __bindgen_bitfield_unit.set(16usize, 8u8, { - let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; - nYear as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Date2 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u8>, - pub __bindgen_align: [u16; 0usize], -} -#[test] -fn bindgen_test_layout_Date2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Date2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(Date2)) - ); -} -impl Date2 { - #[inline] - pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } - } - #[inline] - pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } - } - #[inline] - pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 6u8, val as u64) - } - } - #[inline] - pub fn nMonth(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } - } - #[inline] - pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 5u8, val as u64) - } - } - #[inline] - pub fn nYear(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } - } - #[inline] - pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 8u8, val as u64) - } - } - #[inline] - pub fn byte(&self) -> ::std::os::raw::c_uchar { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u8) } - } - #[inline] - pub fn set_byte(&mut self, val: ::std::os::raw::c_uchar) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 8u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - nWeekDay: ::std::os::raw::c_ushort, - nMonthDay: ::std::os::raw::c_ushort, - nMonth: ::std::os::raw::c_ushort, - nYear: ::std::os::raw::c_ushort, - byte: ::std::os::raw::c_uchar, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; - nWeekDay as u64 - }); - __bindgen_bitfield_unit.set(3usize, 6u8, { - let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; - nMonthDay as u64 - }); - __bindgen_bitfield_unit.set(9usize, 5u8, { - let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; - nMonth as u64 - }); - __bindgen_bitfield_unit.set(16usize, 8u8, { - let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; - nYear as u64 - }); - __bindgen_bitfield_unit.set(24usize, 8u8, { - let byte: u8 = unsafe { ::std::mem::transmute(byte) }; - byte as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Date3 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize], u8>, - pub byte: ::std::os::raw::c_uchar, - pub __bindgen_align: [u16; 0usize], -} -#[test] -fn bindgen_test_layout_Date3() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Date3)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(Date3)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).byte as *const _ as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(Date3), - "::", - stringify!(byte) - ) - ); -} -impl Date3 { - #[inline] - pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u16) } - } - #[inline] - pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 6u8) as u16) } - } - #[inline] - pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 6u8, val as u64) - } - } - #[inline] - pub fn nMonth(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 5u8) as u16) } - } - #[inline] - pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 5u8, val as u64) - } - } - #[inline] - pub fn nYear(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u16) } - } - #[inline] - pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 8u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - nWeekDay: ::std::os::raw::c_ushort, - nMonthDay: ::std::os::raw::c_ushort, - nMonth: ::std::os::raw::c_ushort, - nYear: ::std::os::raw::c_ushort, - ) -> __BindgenBitfieldUnit<[u8; 3usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let nWeekDay: u16 = unsafe { ::std::mem::transmute(nWeekDay) }; - nWeekDay as u64 - }); - __bindgen_bitfield_unit.set(3usize, 6u8, { - let nMonthDay: u16 = unsafe { ::std::mem::transmute(nMonthDay) }; - nMonthDay as u64 - }); - __bindgen_bitfield_unit.set(9usize, 5u8, { - let nMonth: u16 = unsafe { ::std::mem::transmute(nMonth) }; - nMonth as u64 - }); - __bindgen_bitfield_unit.set(16usize, 8u8, { - let nYear: u16 = unsafe { ::std::mem::transmute(nYear) }; - nYear as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/bitfield_align_2.rs b/tests/expectations/tests/bitfield_align_2.rs deleted file mode 100644 index 5d63699d48..0000000000 --- a/tests/expectations/tests/bitfield_align_2.rs +++ /dev/null @@ -1,156 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MyEnum { - ONE = 0, - TWO = 1, - THREE = 2, - FOUR = 3, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TaggedPtr { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_TaggedPtr() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(TaggedPtr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(TaggedPtr)) - ); -} -impl Default for TaggedPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl TaggedPtr { - #[inline] - pub fn tag(&self) -> MyEnum { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u32) } - } - #[inline] - pub fn set_tag(&mut self, val: MyEnum) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 2u8, val as u64) - } - } - #[inline] - pub fn ptr(&self) -> ::std::os::raw::c_long { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 62u8) as u64) } - } - #[inline] - pub fn set_ptr(&mut self, val: ::std::os::raw::c_long) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 62u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - tag: MyEnum, - ptr: ::std::os::raw::c_long, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u64> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u64> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 2u8, { - let tag: u32 = unsafe { ::std::mem::transmute(tag) }; - tag as u64 - }); - __bindgen_bitfield_unit.set(2usize, 62u8, { - let ptr: u64 = unsafe { ::std::mem::transmute(ptr) }; - ptr as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/bitfield_large_overflow.rs b/tests/expectations/tests/bitfield_large_overflow.rs deleted file mode 100644 index e5b254cf76..0000000000 --- a/tests/expectations/tests/bitfield_large_overflow.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct _bindgen_ty_1 { - pub _bindgen_opaque_blob: [u64; 10usize], -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<_bindgen_ty_1>(), - 80usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<_bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); -} -extern "C" { - #[link_name = "\u{1}a"] - pub static mut a: _bindgen_ty_1; -} diff --git a/tests/expectations/tests/bitfield_method_mangling.rs b/tests/expectations/tests/bitfield_method_mangling.rs deleted file mode 100644 index e557f92b2d..0000000000 --- a/tests/expectations/tests/bitfield_method_mangling.rs +++ /dev/null @@ -1,145 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct mach_msg_type_descriptor_t { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_mach_msg_type_descriptor_t() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(mach_msg_type_descriptor_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(mach_msg_type_descriptor_t)) - ); -} -impl mach_msg_type_descriptor_t { - #[inline] - pub fn pad3(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) } - } - #[inline] - pub fn set_pad3(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 24u8, val as u64) - } - } - #[inline] - pub fn type_(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) } - } - #[inline] - pub fn set_type(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 8u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - pad3: ::std::os::raw::c_uint, - type_: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 24u8, { - let pad3: u32 = unsafe { ::std::mem::transmute(pad3) }; - pad3 as u64 - }); - __bindgen_bitfield_unit.set(24usize, 8u8, { - let type_: u32 = unsafe { ::std::mem::transmute(type_) }; - type_ as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/blacklist-and-impl-debug.rs b/tests/expectations/tests/blacklist-and-impl-debug.rs deleted file mode 100644 index a5528af155..0000000000 --- a/tests/expectations/tests/blacklist-and-impl-debug.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub struct BlacklistMe(u8); - - -/// Because this type contains a blacklisted type, it should not derive Debug. -#[repr(C)] -pub struct ShouldManuallyImplDebug { - pub a: BlacklistMe, -} -#[test] -fn bindgen_test_layout_ShouldManuallyImplDebug() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ShouldManuallyImplDebug)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ShouldManuallyImplDebug)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldManuallyImplDebug), - "::", - stringify!(a) - ) - ); -} -impl Default for ShouldManuallyImplDebug { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for ShouldManuallyImplDebug { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "ShouldManuallyImplDebug {{ }}") - } -} diff --git a/tests/expectations/tests/blocks.rs b/tests/expectations/tests/blocks.rs deleted file mode 100644 index 40ee5c5064..0000000000 --- a/tests/expectations/tests/blocks.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn atexit_b(arg1: *mut ::std::os::raw::c_void); -} diff --git a/tests/expectations/tests/builtin-template.rs b/tests/expectations/tests/builtin-template.rs deleted file mode 100644 index 398c3c4aaf..0000000000 --- a/tests/expectations/tests/builtin-template.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type std_make_integer_sequence = u8; diff --git a/tests/expectations/tests/c-empty-layout.rs b/tests/expectations/tests/c-empty-layout.rs deleted file mode 100644 index a14022f54f..0000000000 --- a/tests/expectations/tests/c-empty-layout.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo {} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/canonical_path_without_namespacing.rs b/tests/expectations/tests/canonical_path_without_namespacing.rs deleted file mode 100644 index 02955e4414..0000000000 --- a/tests/expectations/tests/canonical_path_without_namespacing.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bar)) - ); -} -extern "C" { - #[link_name = "\u{1}_Z3bazPN3foo3BarE"] - pub fn baz(arg1: *mut Bar); -} diff --git a/tests/expectations/tests/char.rs b/tests/expectations/tests/char.rs deleted file mode 100644 index ffaae3d190..0000000000 --- a/tests/expectations/tests/char.rs +++ /dev/null @@ -1,103 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type Char = ::std::os::raw::c_char; -pub type SChar = ::std::os::raw::c_schar; -pub type UChar = ::std::os::raw::c_uchar; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Test { - pub ch: ::std::os::raw::c_char, - pub u: ::std::os::raw::c_uchar, - pub d: ::std::os::raw::c_schar, - pub cch: ::std::os::raw::c_char, - pub cu: ::std::os::raw::c_uchar, - pub cd: ::std::os::raw::c_schar, - pub Cch: Char, - pub Cu: UChar, - pub Cd: SChar, - pub Ccch: Char, - pub Ccu: UChar, - pub Ccd: SChar, -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ch as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(ch)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 1usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(u)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 2usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(d)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cch as *const _ as usize }, - 3usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(cch)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cu as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(cu)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cd as *const _ as usize }, - 5usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(cd)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cch as *const _ as usize }, - 6usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cch)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cu as *const _ as usize }, - 7usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cu)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cd as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cd)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccch as *const _ as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Ccch) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccu as *const _ as usize }, - 10usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(Ccu)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccd as *const _ as usize }, - 11usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(Ccd)) - ); -} diff --git a/tests/expectations/tests/class.rs b/tests/expectations/tests/class.rs deleted file mode 100644 index b508395798..0000000000 --- a/tests/expectations/tests/class.rs +++ /dev/null @@ -1,460 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct C { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).big_array as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(big_array) - ) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct C_with_zero_length_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C_with_zero_length_array)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_zero_length_array)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).big_array as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(big_array) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).zero_length_array as *const _ - as usize - }, - 37usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(zero_length_array) - ) - ); -} -impl Default for C_with_zero_length_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_zero_length_array_2 { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(C_with_zero_length_array_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_zero_length_array_2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array_2), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).zero_length_array as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array_2), - "::", - stringify!(zero_length_array) - ) - ); -} -#[repr(C)] -pub struct C_with_incomplete_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_incomplete_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C_with_incomplete_array)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_incomplete_array)) - ); -} -impl Default for C_with_incomplete_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_incomplete_array_2 { - pub a: ::std::os::raw::c_int, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_incomplete_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(C_with_incomplete_array_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_incomplete_array_2)) - ); -} -#[repr(C)] -pub struct C_with_zero_length_array_and_incomplete_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_and_incomplete_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!( - "Size of: ", - stringify!(C_with_zero_length_array_and_incomplete_array) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(C_with_zero_length_array_and_incomplete_array) - ) - ); -} -impl Default for C_with_zero_length_array_and_incomplete_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_zero_length_array_and_incomplete_array_2 { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_and_incomplete_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(C_with_zero_length_array_and_incomplete_array_2) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(C_with_zero_length_array_and_incomplete_array_2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct WithDtor { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_WithDtor() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WithDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithDtor), - "::", - stringify!(b) - ) - ); -} -#[repr(C)] -pub struct IncompleteArrayNonCopiable { - pub whatever: *mut ::std::os::raw::c_void, - pub incomplete_array: __IncompleteArrayField, -} -#[test] -fn bindgen_test_layout_IncompleteArrayNonCopiable() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(IncompleteArrayNonCopiable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(IncompleteArrayNonCopiable)) - ); -} -impl Default for IncompleteArrayNonCopiable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union Union { - pub d: f32, - pub i: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_Union() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Union)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Union)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Union), "::", stringify!(d)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Union), "::", stringify!(i)) - ); -} -impl Default for Union { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct WithUnion { - pub data: Union, -} -#[test] -fn bindgen_test_layout_WithUnion() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WithUnion)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithUnion)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithUnion), - "::", - stringify!(data) - ) - ); -} -impl Default for WithUnion { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct RealAbstractionWithTonsOfMethods { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_RealAbstractionWithTonsOfMethods() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(RealAbstractionWithTonsOfMethods)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of ", - stringify!(RealAbstractionWithTonsOfMethods) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZNK32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar(this: *const RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar1(this: *mut RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEi"] - pub fn RealAbstractionWithTonsOfMethods_bar2( - this: *mut RealAbstractionWithTonsOfMethods, - foo: ::std::os::raw::c_int, - ); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3staEv"] - pub fn RealAbstractionWithTonsOfMethods_sta(); -} -impl RealAbstractionWithTonsOfMethods { - #[inline] - pub unsafe fn bar(&self) { - RealAbstractionWithTonsOfMethods_bar(self) - } - #[inline] - pub unsafe fn bar1(&mut self) { - RealAbstractionWithTonsOfMethods_bar1(self) - } - #[inline] - pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { - RealAbstractionWithTonsOfMethods_bar2(self, foo) - } - #[inline] - pub unsafe fn sta() { - RealAbstractionWithTonsOfMethods_sta() - } -} diff --git a/tests/expectations/tests/class_1_0.rs b/tests/expectations/tests/class_1_0.rs deleted file mode 100644 index 333a6eb4be..0000000000 --- a/tests/expectations/tests/class_1_0.rs +++ /dev/null @@ -1,518 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Copy)] -pub struct C { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).big_array as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(big_array) - ) - ); -} -impl Clone for C { - fn clone(&self) -> Self { - *self - } -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for C { - fn eq(&self, other: &C) -> bool { - self.a == other.a && &self.big_array[..] == &other.big_array[..] - } -} -#[repr(C)] -pub struct C_with_zero_length_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C_with_zero_length_array)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_zero_length_array)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).big_array as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(big_array) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).zero_length_array as *const _ - as usize - }, - 37usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array), - "::", - stringify!(zero_length_array) - ) - ); -} -impl Default for C_with_zero_length_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_zero_length_array_2 { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(C_with_zero_length_array_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_zero_length_array_2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array_2), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).zero_length_array as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_with_zero_length_array_2), - "::", - stringify!(zero_length_array) - ) - ); -} -#[repr(C)] -pub struct C_with_incomplete_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_incomplete_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(C_with_incomplete_array)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_incomplete_array)) - ); -} -impl Default for C_with_incomplete_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_incomplete_array_2 { - pub a: ::std::os::raw::c_int, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_incomplete_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(C_with_incomplete_array_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_with_incomplete_array_2)) - ); -} -#[repr(C)] -pub struct C_with_zero_length_array_and_incomplete_array { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_and_incomplete_array() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!( - "Size of: ", - stringify!(C_with_zero_length_array_and_incomplete_array) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(C_with_zero_length_array_and_incomplete_array) - ) - ); -} -impl Default for C_with_zero_length_array_and_incomplete_array { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct C_with_zero_length_array_and_incomplete_array_2 { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_C_with_zero_length_array_and_incomplete_array_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(C_with_zero_length_array_and_incomplete_array_2) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(C_with_zero_length_array_and_incomplete_array_2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Hash, PartialEq, Eq)] -pub struct WithDtor { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_WithDtor() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WithDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithDtor), - "::", - stringify!(b) - ) - ); -} -#[repr(C)] -pub struct IncompleteArrayNonCopiable { - pub whatever: *mut ::std::os::raw::c_void, - pub incomplete_array: __IncompleteArrayField, -} -#[test] -fn bindgen_test_layout_IncompleteArrayNonCopiable() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(IncompleteArrayNonCopiable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(IncompleteArrayNonCopiable)) - ); -} -impl Default for IncompleteArrayNonCopiable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct Union { - pub d: __BindgenUnionField, - pub i: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_Union() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Union)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Union)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Union), "::", stringify!(d)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Union), "::", stringify!(i)) - ); -} -impl Clone for Union { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct WithUnion { - pub data: Union, -} -#[test] -fn bindgen_test_layout_WithUnion() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WithUnion)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithUnion)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithUnion), - "::", - stringify!(data) - ) - ); -} -impl Clone for WithUnion { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct RealAbstractionWithTonsOfMethods { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_RealAbstractionWithTonsOfMethods() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(RealAbstractionWithTonsOfMethods)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of ", - stringify!(RealAbstractionWithTonsOfMethods) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZNK32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar(this: *const RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar1(this: *mut RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3barEi"] - pub fn RealAbstractionWithTonsOfMethods_bar2( - this: *mut RealAbstractionWithTonsOfMethods, - foo: ::std::os::raw::c_int, - ); -} -extern "C" { - #[link_name = "\u{1}_ZN32RealAbstractionWithTonsOfMethods3staEv"] - pub fn RealAbstractionWithTonsOfMethods_sta(); -} -impl Clone for RealAbstractionWithTonsOfMethods { - fn clone(&self) -> Self { - *self - } -} -impl RealAbstractionWithTonsOfMethods { - #[inline] - pub unsafe fn bar(&self) { - RealAbstractionWithTonsOfMethods_bar(self) - } - #[inline] - pub unsafe fn bar1(&mut self) { - RealAbstractionWithTonsOfMethods_bar1(self) - } - #[inline] - pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { - RealAbstractionWithTonsOfMethods_bar2(self, foo) - } - #[inline] - pub unsafe fn sta() { - RealAbstractionWithTonsOfMethods_sta() - } -} diff --git a/tests/expectations/tests/class_nested.rs b/tests/expectations/tests/class_nested.rs deleted file mode 100644 index 7fee662a92..0000000000 --- a/tests/expectations/tests/class_nested.rs +++ /dev/null @@ -1,168 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A { - pub member_a: ::std::os::raw::c_int, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A_B { - pub member_b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A_B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A_B)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member_b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A_B), - "::", - stringify!(member_b) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A_D { - pub foo: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for A_D { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member_a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A), - "::", - stringify!(member_a) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A_C { - pub baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_C() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A_C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A_C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A_C), "::", stringify!(baz)) - ); -} -extern "C" { - #[link_name = "\u{1}var"] - pub static mut var: A_B; -} -#[test] -fn __bindgen_test_layout_A_D_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(A_D<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(A_D<::std::os::raw::c_int>) - ) - ); -} -extern "C" { - #[link_name = "\u{1}baz"] - pub static mut baz: A_D<::std::os::raw::c_int>; -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct D { - pub member: A_B, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(D)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(D)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(D), "::", stringify!(member)) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Templated { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Templated_Templated_inner { - pub member_ptr: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Templated_Templated_inner { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for Templated { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/class_no_members.rs b/tests/expectations/tests/class_no_members.rs deleted file mode 100644 index 7da77892b9..0000000000 --- a/tests/expectations/tests/class_no_members.rs +++ /dev/null @@ -1,72 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct whatever { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_whatever() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(whatever)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(whatever)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct whatever_child { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_whatever_child() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(whatever_child)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(whatever_child)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct whatever_child_with_member { - pub m_member: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_whatever_child_with_member() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(whatever_child_with_member)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(whatever_child_with_member)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).m_member as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(whatever_child_with_member), - "::", - stringify!(m_member) - ) - ); -} diff --git a/tests/expectations/tests/class_static.rs b/tests/expectations/tests/class_static.rs deleted file mode 100644 index c28366c134..0000000000 --- a/tests/expectations/tests/class_static.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct MyClass { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN7MyClass7exampleE"] - pub static mut MyClass_example: *const ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}_ZN7MyClass26example_check_no_collisionE"] - pub static mut MyClass_example_check_no_collision: *const ::std::os::raw::c_int; -} -#[test] -fn bindgen_test_layout_MyClass() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(MyClass)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(MyClass)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZL26example_check_no_collision"] - pub static mut example_check_no_collision: *const ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/class_static_const.rs b/tests/expectations/tests/class_static_const.rs deleted file mode 100644 index c0945c4337..0000000000 --- a/tests/expectations/tests/class_static_const.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A { - pub _address: u8, -} -pub const A_a: ::std::os::raw::c_int = 0; -pub const A_b: i32 = 63; -pub const A_c: u32 = 255; -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} diff --git a/tests/expectations/tests/class_use_as.rs b/tests/expectations/tests/class_use_as.rs deleted file mode 100644 index 5882328d9b..0000000000 --- a/tests/expectations/tests/class_use_as.rs +++ /dev/null @@ -1,64 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct whatever { - pub replacement: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_whatever() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(whatever)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(whatever)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).replacement as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(whatever), - "::", - stringify!(replacement) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct container { - pub c: whatever, -} -#[test] -fn bindgen_test_layout_container() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(container)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(container)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(container), - "::", - stringify!(c) - ) - ); -} diff --git a/tests/expectations/tests/class_with_dtor.rs b/tests/expectations/tests/class_with_dtor.rs deleted file mode 100644 index 4a5b090d8a..0000000000 --- a/tests/expectations/tests/class_with_dtor.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct HandleWithDtor { - pub ptr: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for HandleWithDtor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct WithoutDtor { - pub shouldBeWithDtor: HandleValue, -} -#[test] -fn bindgen_test_layout_WithoutDtor() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(WithoutDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(WithoutDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).shouldBeWithDtor as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithoutDtor), - "::", - stringify!(shouldBeWithDtor) - ) - ); -} -impl Default for WithoutDtor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); -} diff --git a/tests/expectations/tests/class_with_inner_struct.rs b/tests/expectations/tests/class_with_inner_struct.rs deleted file mode 100644 index 265d7c5bfc..0000000000 --- a/tests/expectations/tests/class_with_inner_struct.rs +++ /dev/null @@ -1,442 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct A { - pub c: ::std::os::raw::c_uint, - pub named_union: A__bindgen_ty_1, - pub __bindgen_anon_1: A__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct A_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(A_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(A_Segment), - "::", - stringify!(end) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union A__bindgen_ty_1 { - pub f: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A__bindgen_ty_1), - "::", - stringify!(f) - ) - ); -} -impl Default for A__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union A__bindgen_ty_2 { - pub d: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A__bindgen_ty_2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A__bindgen_ty_2), - "::", - stringify!(d) - ) - ); -} -impl Default for A__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::
(), - 12usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(c)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).named_union as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(A), - "::", - stringify!(named_union) - ) - ); -} -impl Default for A { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct B { - pub d: ::std::os::raw::c_uint, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct B_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_B_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(B_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(B_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(B_Segment), - "::", - stringify!(end) - ) - ); -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(B), "::", stringify!(d)) - ); -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum StepSyntax { - Keyword = 0, - FunctionalWithoutKeyword = 1, - FunctionalWithStartKeyword = 2, - FunctionalWithEndKeyword = 3, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct C { - pub d: ::std::os::raw::c_uint, - pub __bindgen_anon_1: C__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union C__bindgen_ty_1 { - pub mFunc: C__bindgen_ty_1__bindgen_ty_1, - pub __bindgen_anon_1: C__bindgen_ty_1__bindgen_ty_2, - _bindgen_union_align: [u32; 4usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct C__bindgen_ty_1__bindgen_ty_1 { - pub mX1: f32, - pub mY1: f32, - pub mX2: f32, - pub mY2: f32, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mX1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mX1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mY1 as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mY1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mX2 as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mX2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mY2 as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mY2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct C__bindgen_ty_1__bindgen_ty_2 { - pub mStepSyntax: StepSyntax, - pub mSteps: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mStepSyntax as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(mStepSyntax) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mSteps as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(mSteps) - ) - ); -} -impl Default for C__bindgen_ty_1__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFunc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1), - "::", - stringify!(mFunc) - ) - ); -} -impl Default for C__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct C_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_Segment), - "::", - stringify!(end) - ) - ); -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(d)) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/class_with_inner_struct_1_0.rs b/tests/expectations/tests/class_with_inner_struct_1_0.rs deleted file mode 100644 index a2c01b4e65..0000000000 --- a/tests/expectations/tests/class_with_inner_struct_1_0.rs +++ /dev/null @@ -1,515 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct A { - pub c: ::std::os::raw::c_uint, - pub named_union: A__bindgen_ty_1, - pub __bindgen_anon_1: A__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct A_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(A_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(A_Segment), - "::", - stringify!(end) - ) - ); -} -impl Clone for A_Segment { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct A__bindgen_ty_1 { - pub f: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A__bindgen_ty_1), - "::", - stringify!(f) - ) - ); -} -impl Clone for A__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct A__bindgen_ty_2 { - pub d: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A__bindgen_ty_2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(A__bindgen_ty_2), - "::", - stringify!(d) - ) - ); -} -impl Clone for A__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(c)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).named_union as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(A), - "::", - stringify!(named_union) - ) - ); -} -impl Clone for A { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct B { - pub d: ::std::os::raw::c_uint, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct B_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_B_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(B_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(B_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(B_Segment), - "::", - stringify!(end) - ) - ); -} -impl Clone for B_Segment { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(B), "::", stringify!(d)) - ); -} -impl Clone for B { - fn clone(&self) -> Self { - *self - } -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum StepSyntax { - Keyword = 0, - FunctionalWithoutKeyword = 1, - FunctionalWithStartKeyword = 2, - FunctionalWithEndKeyword = 3, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct C { - pub d: ::std::os::raw::c_uint, - pub __bindgen_anon_1: C__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct C__bindgen_ty_1 { - pub mFunc: __BindgenUnionField, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: [u32; 4usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, PartialEq)] -pub struct C__bindgen_ty_1__bindgen_ty_1 { - pub mX1: f32, - pub mY1: f32, - pub mX2: f32, - pub mY2: f32, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mX1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mX1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mY1 as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mY1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mX2 as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mX2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mY2 as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(mY2) - ) - ); -} -impl Clone for C__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct C__bindgen_ty_1__bindgen_ty_2 { - pub mStepSyntax: StepSyntax, - pub mSteps: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mStepSyntax as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(mStepSyntax) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mSteps as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(mSteps) - ) - ); -} -impl Clone for C__bindgen_ty_1__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -impl Default for C__bindgen_ty_1__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFunc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C__bindgen_ty_1), - "::", - stringify!(mFunc) - ) - ); -} -impl Clone for C__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct C_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C_Segment() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C_Segment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C_Segment)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).begin as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C_Segment), - "::", - stringify!(begin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).end as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C_Segment), - "::", - stringify!(end) - ) - ); -} -impl Clone for C_Segment { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(d)) - ); -} -impl Clone for C { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/class_with_typedef.rs b/tests/expectations/tests/class_with_typedef.rs deleted file mode 100644 index 221ed5d7cb..0000000000 --- a/tests/expectations/tests/class_with_typedef.rs +++ /dev/null @@ -1,129 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type AnotherInt = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct C { - pub c: C_MyInt, - pub ptr: *mut C_MyInt, - pub arr: [C_MyInt; 10usize], - pub d: AnotherInt, - pub other_ptr: *mut AnotherInt, -} -pub type C_MyInt = ::std::os::raw::c_int; -pub type C_Lookup = *const ::std::os::raw::c_char; -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 72usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(c)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(ptr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arr as *const _ as usize }, - 16usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(arr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 56usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(d)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).other_ptr as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(other_ptr) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN1C6methodEi"] - pub fn C_method(this: *mut C, c: C_MyInt); -} -extern "C" { - #[link_name = "\u{1}_ZN1C9methodRefERi"] - pub fn C_methodRef(this: *mut C, c: *mut C_MyInt); -} -extern "C" { - #[link_name = "\u{1}_ZN1C16complexMethodRefERPKc"] - pub fn C_complexMethodRef(this: *mut C, c: *mut C_Lookup); -} -extern "C" { - #[link_name = "\u{1}_ZN1C13anotherMethodEi"] - pub fn C_anotherMethod(this: *mut C, c: AnotherInt); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl C { - #[inline] - pub unsafe fn method(&mut self, c: C_MyInt) { - C_method(self, c) - } - #[inline] - pub unsafe fn methodRef(&mut self, c: *mut C_MyInt) { - C_methodRef(self, c) - } - #[inline] - pub unsafe fn complexMethodRef(&mut self, c: *mut C_Lookup) { - C_complexMethodRef(self, c) - } - #[inline] - pub unsafe fn anotherMethod(&mut self, c: AnotherInt) { - C_anotherMethod(self, c) - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct D { - pub _base: C, - pub ptr: *mut C_MyInt, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!( - ::std::mem::size_of::(), - 80usize, - concat!("Size of: ", stringify!(D)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(D)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 72usize, - concat!("Offset of field: ", stringify!(D), "::", stringify!(ptr)) - ); -} -impl Default for D { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/comment-indent.rs b/tests/expectations/tests/comment-indent.rs deleted file mode 100644 index 97afeefa95..0000000000 --- a/tests/expectations/tests/comment-indent.rs +++ /dev/null @@ -1,132 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - /// This is a multi-line doc comment. - /// - /// This class is really really interesting, look! - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Foo { - pub _address: u8, - } - /// This nested class is also a multi-line doc comment. - /// - /// This class is not so interesting, but worth a bit of docs too! - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Foo_Bar { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Foo_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo_Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo_Bar)) - ); - } - #[test] - fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); - } - pub mod test { - #[allow(unused_imports)] - use self::super::super::root; - /// I'm in a namespace, and thus I may be on a rust module, most of the time. - /// My documentation is pretty extensive, I guess. - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Baz { - /// This member is plain awesome, just amazing. - /// - /// It also has super-extensive docs, with even a nice ascii-art diagram. - /// - /// +------+ +-------+ - /// | foo | ----> | bar | - /// +------+ +-------+ - pub member: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Baz), - "::", - stringify!(member) - ) - ); - } - /// I'm in an inline namespace, and as such I shouldn't get generated inside - /// a rust module, except when the relevant option is specified. Also, this - /// comment shouldn't be misaligned. - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct InInlineNS { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_InInlineNS() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(InInlineNS)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(InInlineNS)) - ); - } - - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bazz { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Bazz() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bazz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bazz)) - ); - } - } -} diff --git a/tests/expectations/tests/complex.rs b/tests/expectations/tests/complex.rs deleted file mode 100644 index 317bb99a5e..0000000000 --- a/tests/expectations/tests/complex.rs +++ /dev/null @@ -1,134 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct TestDouble { - pub mMember: __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestDouble() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(TestDouble)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(TestDouble)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mMember as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(TestDouble), - "::", - stringify!(mMember) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct TestDoublePtr { - pub mMember: *mut __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestDoublePtr() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(TestDoublePtr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(TestDoublePtr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mMember as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(TestDoublePtr), - "::", - stringify!(mMember) - ) - ); -} -impl Default for TestDoublePtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct TestFloat { - pub mMember: __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestFloat() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(TestFloat)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(TestFloat)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mMember as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(TestFloat), - "::", - stringify!(mMember) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct TestFloatPtr { - pub mMember: *mut __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestFloatPtr() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(TestFloatPtr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(TestFloatPtr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mMember as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(TestFloatPtr), - "::", - stringify!(mMember) - ) - ); -} -impl Default for TestFloatPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/complex_global.rs b/tests/expectations/tests/complex_global.rs deleted file mode 100644 index defdbe68ca..0000000000 --- a/tests/expectations/tests/complex_global.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -extern "C" { - #[link_name = "\u{1}globalValueFloat"] - pub static mut globalValueFloat: __BindgenComplex; -} -extern "C" { - #[link_name = "\u{1}globalValueDouble"] - pub static mut globalValueDouble: __BindgenComplex; -} -extern "C" { - #[link_name = "\u{1}globalValueLongDouble"] - pub static mut globalValueLongDouble: __BindgenComplex; -} diff --git a/tests/expectations/tests/const_array_fn_arg.rs b/tests/expectations/tests/const_array_fn_arg.rs deleted file mode 100644 index 5e934bcbb5..0000000000 --- a/tests/expectations/tests/const_array_fn_arg.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn f(a: *const ::std::os::raw::c_int); -} diff --git a/tests/expectations/tests/const_enum_unnamed.rs b/tests/expectations/tests/const_enum_unnamed.rs deleted file mode 100644 index 6b04c7dd4c..0000000000 --- a/tests/expectations/tests/const_enum_unnamed.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR; -pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - FOO_BAR = 0, - FOO_BAZ = 1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo__bindgen_ty_1 { - FOO_BAR = 10, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/const_ptr.rs b/tests/expectations/tests/const_ptr.rs deleted file mode 100644 index 9831cd8dc4..0000000000 --- a/tests/expectations/tests/const_ptr.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(bar: *const ::std::os::raw::c_void); -} diff --git a/tests/expectations/tests/const_resolved_ty.rs b/tests/expectations/tests/const_resolved_ty.rs deleted file mode 100644 index 7c4b91b007..0000000000 --- a/tests/expectations/tests/const_resolved_ty.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(foo: *const u8); -} diff --git a/tests/expectations/tests/const_tparam.rs b/tests/expectations/tests/const_tparam.rs deleted file mode 100644 index 218abbdbce..0000000000 --- a/tests/expectations/tests/const_tparam.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct C { - pub foo: *const T, - pub bar: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/constify-all-enums.rs b/tests/expectations/tests/constify-all-enums.rs deleted file mode 100644 index b2e1e974ea..0000000000 --- a/tests/expectations/tests/constify-all-enums.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const foo_THIS: foo = 0; -pub const foo_SHOULD_BE: foo = 1; -pub const foo_A_CONSTANT: foo = 2; -pub type foo = u32; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct bar { - pub this_should_work: foo, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).this_should_work as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(this_should_work) - ) - ); -} -impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/constify-enum.rs b/tests/expectations/tests/constify-enum.rs deleted file mode 100644 index 07279cf301..0000000000 --- a/tests/expectations/tests/constify-enum.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const nsCSSPropertyID_eCSSProperty_COUNT_unexistingVariantValue: nsCSSPropertyID = - nsCSSPropertyID::eCSSProperty_COUNT_unexistingVariantValue; -pub const nsCSSPropertyID_eCSSProperty_COUNT: nsCSSPropertyID = - nsCSSPropertyID::eCSSPropertyAlias_aa; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum nsCSSPropertyID { - eCSSProperty_a = 0, - eCSSProperty_b = 1, - eCSSPropertyAlias_aa = 2, - eCSSPropertyAlias_bb = 3, - /// <
- eCSSProperty_COUNT_unexistingVariantValue = 4, -} diff --git a/tests/expectations/tests/constify-module-enums-basic.rs b/tests/expectations/tests/constify-module-enums-basic.rs deleted file mode 100644 index 342e5ba525..0000000000 --- a/tests/expectations/tests/constify-module-enums-basic.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod foo { - pub type Type = u32; - pub const THIS: Type = 0; - pub const SHOULD_BE: Type = 1; - pub const A_CONSTANT: Type = 2; -} -pub use self::foo::Type as foo_alias1; -pub use self::foo_alias1 as foo_alias2; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct bar { - pub this_should_work: foo::Type, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).this_should_work as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(this_should_work) - ) - ); -} -impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - pub fn func1( - arg1: foo::Type, - arg2: *mut foo::Type, - arg3: *mut *mut foo::Type, - ) -> *mut foo::Type; -} -extern "C" { - pub fn func2( - arg1: foo_alias1, - arg2: *mut foo_alias1, - arg3: *mut *mut foo_alias1, - ) -> *mut foo_alias1; -} diff --git a/tests/expectations/tests/constify-module-enums-namespace.rs b/tests/expectations/tests/constify-module-enums-namespace.rs deleted file mode 100644 index 7f1c134d3c..0000000000 --- a/tests/expectations/tests/constify-module-enums-namespace.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod ns1 { - #[allow(unused_imports)] - use self::super::super::root; - pub mod ns2 { - #[allow(unused_imports)] - use self::super::super::super::root; - pub mod foo { - pub type Type = u32; - pub const THIS: Type = 0; - pub const SHOULD_BE: Type = 1; - pub const A_CONSTANT: Type = 2; - } - } - pub mod ns3 { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct bar { - pub this_should_work: root::ns1::ns2::foo::Type, - } - #[test] - fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).this_should_work as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(this_should_work) - ) - ); - } - impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - } - } -} diff --git a/tests/expectations/tests/constify-module-enums-shadow-name.rs b/tests/expectations/tests/constify-module-enums-shadow-name.rs deleted file mode 100644 index 9642871745..0000000000 --- a/tests/expectations/tests/constify-module-enums-shadow-name.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod foo { - pub type Type = u32; - pub const Type: Type = 0; - pub const Type_: Type = 1; - pub const Type1: Type = 2; - pub const Type__: Type = 3; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct bar { - pub member: foo::Type, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member) - ) - ); -} -impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/constify-module-enums-simple-alias.rs b/tests/expectations/tests/constify-module-enums-simple-alias.rs deleted file mode 100644 index 70c881b9f4..0000000000 --- a/tests/expectations/tests/constify-module-enums-simple-alias.rs +++ /dev/null @@ -1,103 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod Foo { - pub type Type = i32; - pub const Variant1: Type = 0; - pub const Variant2: Type = 1; - pub const Variant3: Type = 2; -} -pub use self::Foo::Type as Foo_alias1; -pub use self::Foo_alias1 as Foo_alias2; -pub use self::Foo_alias2 as Foo_alias3; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Bar { - pub baz1: Foo::Type, - pub baz2: Foo_alias1, - pub baz3: Foo_alias2, - pub baz4: Foo_alias3, - pub baz_ptr1: *mut Foo::Type, - pub baz_ptr2: *mut Foo_alias1, - pub baz_ptr3: *mut Foo_alias2, - pub baz_ptr4: *mut Foo_alias3, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz1 as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz2 as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz3 as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz3)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz4 as *const _ as usize }, - 12usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz4)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz_ptr1 as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(baz_ptr1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz_ptr2 as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(baz_ptr2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz_ptr3 as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(baz_ptr3) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz_ptr4 as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(baz_ptr4) - ) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs b/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs deleted file mode 100644 index ee15b57be5..0000000000 --- a/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod one_Foo { - pub type Type = i32; - pub const Variant1: Type = 0; - pub const Variant2: Type = 1; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Bar { - pub baz1: one_Foo::Type, - pub baz2: *mut one_Foo::Type, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz1 as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz2 as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz2)) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/constify-module-enums-types.rs b/tests/expectations/tests/constify-module-enums-types.rs deleted file mode 100644 index 155839be7c..0000000000 --- a/tests/expectations/tests/constify-module-enums-types.rs +++ /dev/null @@ -1,269 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod foo { - pub type Type = u32; - pub const THIS: Type = 0; - pub const SHOULD_BE: Type = 1; - pub const A_CONSTANT: Type = 2; - pub const ALSO_THIS: Type = 42; - pub const AND_ALSO_THIS: Type = 42; -} -pub mod anon_enum { - pub type Type = u32; - pub const Variant1: Type = 0; - pub const Variant2: Type = 1; - pub const Variant3: Type = 2; -} -pub mod ns1_foo { - pub type Type = u32; - pub const THIS: Type = 0; - pub const SHOULD_BE: Type = 1; - pub const A_CONSTANT: Type = 2; - pub const ALSO_THIS: Type = 42; -} -pub mod ns2_Foo { - pub type Type = i32; - pub const Variant1: Type = 0; - pub const Variant2: Type = 1; -} -pub use self::foo::Type as foo_alias1; -pub use self::foo_alias1 as foo_alias2; -pub use self::foo_alias2 as foo_alias3; -pub use self::anon_enum::Type as anon_enum_alias1; -pub use self::anon_enum_alias1 as anon_enum_alias2; -pub use self::anon_enum_alias2 as anon_enum_alias3; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct bar { - pub member1: foo::Type, - pub member2: foo_alias1, - pub member3: foo_alias2, - pub member4: foo_alias3, - pub member5: ns1_foo::Type, - pub member6: *mut ns2_Foo::Type, - pub member7: anon_enum::Type, - pub member8: anon_enum_alias1, - pub member9: anon_enum_alias2, - pub member10: anon_enum_alias3, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member1 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member2 as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member3 as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member3) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member4 as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member4) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member5 as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member5) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member6 as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member6) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member7 as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member7) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member8 as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member8) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member9 as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member9) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member10 as *const _ as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(bar), - "::", - stringify!(member10) - ) - ); -} -impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Baz { - pub member1: ns2_Foo::Type, -} -#[test] -fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member1 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Baz), - "::", - stringify!(member1) - ) - ); -} -impl Default for Baz { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub mod one_Foo { - pub type Type = i32; - pub const Variant1: Type = 0; - pub const Variant2: Type = 1; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Bar { - pub baz: *mut one_Foo::Type, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz)) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z5func13fooPS_PS0_"] - pub fn func1( - arg1: foo::Type, - arg2: *mut foo::Type, - arg3: *mut *mut foo::Type, - ) -> *mut foo::Type; -} -extern "C" { - #[link_name = "\u{1}_Z5func23fooPS_PS0_"] - pub fn func2( - arg1: foo_alias1, - arg2: *mut foo_alias1, - arg3: *mut *mut foo_alias1, - ) -> *mut foo_alias1; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Thing { - pub thing: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Thing { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z5func35ThingI3fooE"] - pub fn func3(arg1: Thing) -> foo::Type; -} -extern "C" { - #[link_name = "\u{1}_Z5func45ThingIS_I3fooEE"] - pub fn func4(arg1: Thing>) -> foo::Type; -} diff --git a/tests/expectations/tests/constructor-tp.rs b/tests/expectations/tests/constructor-tp.rs deleted file mode 100644 index 7336024850..0000000000 --- a/tests/expectations/tests/constructor-tp.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bar)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3BarC1Ev"] - pub fn Bar_Bar(this: *mut Bar); -} -impl Bar { - #[inline] - pub unsafe fn new() -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - Bar_Bar(&mut __bindgen_tmp); - __bindgen_tmp - } -} diff --git a/tests/expectations/tests/constructors.rs b/tests/expectations/tests/constructors.rs deleted file mode 100644 index b20e3f44d5..0000000000 --- a/tests/expectations/tests/constructors.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct TestOverload { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_TestOverload() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(TestOverload)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(TestOverload)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN12TestOverloadC1Ei"] - pub fn TestOverload_TestOverload(this: *mut TestOverload, arg1: ::std::os::raw::c_int); -} -extern "C" { - #[link_name = "\u{1}_ZN12TestOverloadC1Ed"] - pub fn TestOverload_TestOverload1(this: *mut TestOverload, arg1: f64); -} -impl TestOverload { - #[inline] - pub unsafe fn new(arg1: ::std::os::raw::c_int) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - TestOverload_TestOverload(&mut __bindgen_tmp, arg1); - __bindgen_tmp - } - #[inline] - pub unsafe fn new1(arg1: f64) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - TestOverload_TestOverload1(&mut __bindgen_tmp, arg1); - __bindgen_tmp - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct TestPublicNoArgs { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_TestPublicNoArgs() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(TestPublicNoArgs)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(TestPublicNoArgs)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN16TestPublicNoArgsC1Ev"] - pub fn TestPublicNoArgs_TestPublicNoArgs(this: *mut TestPublicNoArgs); -} -impl TestPublicNoArgs { - #[inline] - pub unsafe fn new() -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - TestPublicNoArgs_TestPublicNoArgs(&mut __bindgen_tmp); - __bindgen_tmp - } -} diff --git a/tests/expectations/tests/contains-vs-inherits-zero-sized.rs b/tests/expectations/tests/contains-vs-inherits-zero-sized.rs deleted file mode 100644 index 16139a0647..0000000000 --- a/tests/expectations/tests/contains-vs-inherits-zero-sized.rs +++ /dev/null @@ -1,97 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This should get an `_address` byte. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Empty { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Empty() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Empty)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Empty)) - ); -} -/// This should not get an `_address` byte, so `sizeof(Inherits)` should be -/// `1`. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Inherits { - pub b: bool, -} -#[test] -fn bindgen_test_layout_Inherits() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Inherits)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Inherits)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Inherits), - "::", - stringify!(b) - ) - ); -} -/// This should not get an `_address` byte, but contains `Empty` which *does* get -/// one, so `sizeof(Contains)` should be `1 + 1`. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Contains { - pub empty: Empty, - pub b: bool, -} -#[test] -fn bindgen_test_layout_Contains() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(Contains)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Contains)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).empty as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Contains), - "::", - stringify!(empty) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(Contains), - "::", - stringify!(b) - ) - ); -} diff --git a/tests/expectations/tests/convert-cpp-comment-to-rust.rs b/tests/expectations/tests/convert-cpp-comment-to-rust.rs deleted file mode 100644 index f9f8e200d1..0000000000 --- a/tests/expectations/tests/convert-cpp-comment-to-rust.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type mbedtls_mpi_uint = ::std::os::raw::c_uint; -/// \brief MPI structure -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct mbedtls_mpi { - /// < integer sign - pub s: ::std::os::raw::c_int, - /// < total # of limbs - pub n: ::std::os::raw::c_ulong, - /// < pointer to limbs - pub p: *mut mbedtls_mpi_uint, -} -#[test] -fn bindgen_test_layout_mbedtls_mpi() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(mbedtls_mpi)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(mbedtls_mpi)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mbedtls_mpi), - "::", - stringify!(s) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).n as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(mbedtls_mpi), - "::", - stringify!(n) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).p as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(mbedtls_mpi), - "::", - stringify!(p) - ) - ); -} -impl Default for mbedtls_mpi { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/convert-floats.rs b/tests/expectations/tests/convert-floats.rs deleted file mode 100644 index e1e93a1343..0000000000 --- a/tests/expectations/tests/convert-floats.rs +++ /dev/null @@ -1,85 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct foo { - pub bar: ::std::os::raw::c_float, - pub baz: ::std::os::raw::c_float, - pub bazz: ::std::os::raw::c_double, - pub bazzz: *mut ::std::os::raw::c_double, - pub complexFloat: __BindgenComplex<::std::os::raw::c_float>, - pub complexDouble: __BindgenComplex<::std::os::raw::c_double>, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bazz as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bazz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bazzz as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(foo), - "::", - stringify!(bazzz) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).complexFloat as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(foo), - "::", - stringify!(complexFloat) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).complexDouble as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(foo), - "::", - stringify!(complexDouble) - ) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/cpp-empty-layout.rs b/tests/expectations/tests/cpp-empty-layout.rs deleted file mode 100644 index 36cae7222f..0000000000 --- a/tests/expectations/tests/cpp-empty-layout.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/crtp.rs b/tests/expectations/tests/crtp.rs deleted file mode 100644 index c56cceb2e8..0000000000 --- a/tests/expectations/tests/crtp.rs +++ /dev/null @@ -1,85 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Base { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Derived { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Derived() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Derived)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Derived)) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct BaseWithDestructor { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct DerivedFromBaseWithDestructor { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_DerivedFromBaseWithDestructor() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(DerivedFromBaseWithDestructor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(DerivedFromBaseWithDestructor)) - ); -} -#[test] -fn __bindgen_test_layout_Base_open0_Derived_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of template specialization: ", stringify!(Base)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of template specialization: ", stringify!(Base)) - ); -} -#[test] -fn __bindgen_test_layout_BaseWithDestructor_open0_DerivedFromBaseWithDestructor_close0_instantiation( -) { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!( - "Size of template specialization: ", - stringify!(BaseWithDestructor) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(BaseWithDestructor) - ) - ); -} diff --git a/tests/expectations/tests/decl_extern_int_twice.rs b/tests/expectations/tests/decl_extern_int_twice.rs deleted file mode 100644 index 995457587e..0000000000 --- a/tests/expectations/tests/decl_extern_int_twice.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}foo"] - pub static mut foo: ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/decl_ptr_to_array.rs b/tests/expectations/tests/decl_ptr_to_array.rs deleted file mode 100644 index 6d6eeb4b88..0000000000 --- a/tests/expectations/tests/decl_ptr_to_array.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}foo"] - pub static mut foo: *mut [::std::os::raw::c_int; 1usize]; -} diff --git a/tests/expectations/tests/default-template-parameter.rs b/tests/expectations/tests/default-template-parameter.rs deleted file mode 100644 index 8d4ba3dd4f..0000000000 --- a/tests/expectations/tests/default-template-parameter.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - pub t: T, - pub u: U, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_Foo_open0_bool__int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify ! ( Foo < bool , :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify ! ( Foo < bool , :: std :: os :: raw :: c_int > ) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZL3bar"] - pub static mut bar: Foo; -} diff --git a/tests/expectations/tests/derive-bitfield-method-same-name.rs b/tests/expectations/tests/derive-bitfield-method-same-name.rs deleted file mode 100644 index f9d29afd13..0000000000 --- a/tests/expectations/tests/derive-bitfield-method-same-name.rs +++ /dev/null @@ -1,192 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} - -/// Because this struct have array larger than 32 items -/// and --with-derive-partialeq --impl-partialeq --impl-debug is provided, -/// this struct should manually implement `Debug` and `PartialEq`. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Foo { - pub large: [::std::os::raw::c_int; 33usize], - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, - pub __bindgen_padding_0: u16, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 136usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Foo), - "::", - stringify!(large) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4typeEv"] - pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo9set_type_Ec"] - pub fn Foo_set_type_(this: *mut Foo, c: ::std::os::raw::c_char); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo8set_typeEc"] - pub fn Foo_set_type(this: *mut Foo, c: ::std::os::raw::c_char); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for Foo { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!( - f, - "Foo {{ large: [{}], type_ : {:?}, }}", - self.large - .iter() - .enumerate() - .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) - .collect::(), - self.type__bindgen_bitfield() - ) - } -} -impl ::std::cmp::PartialEq for Foo { - fn eq(&self, other: &Foo) -> bool { - &self.large[..] == &other.large[..] - && self.type__bindgen_bitfield() == other.type__bindgen_bitfield() - } -} -impl Foo { - #[inline] - pub fn type__bindgen_bitfield(&self) -> ::std::os::raw::c_char { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u8) } - } - #[inline] - pub fn set_type__bindgen_bitfield(&mut self, val: ::std::os::raw::c_char) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - type__bindgen_bitfield: ::std::os::raw::c_char, - ) -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let type__bindgen_bitfield: u8 = - unsafe { ::std::mem::transmute(type__bindgen_bitfield) }; - type__bindgen_bitfield as u64 - }); - __bindgen_bitfield_unit - } - #[inline] - pub unsafe fn type_(&mut self) -> ::std::os::raw::c_char { - Foo_type(self) - } - #[inline] - pub unsafe fn set_type_(&mut self, c: ::std::os::raw::c_char) { - Foo_set_type_(self, c) - } - #[inline] - pub unsafe fn set_type(&mut self, c: ::std::os::raw::c_char) { - Foo_set_type(self, c) - } -} diff --git a/tests/expectations/tests/derive-clone.rs b/tests/expectations/tests/derive-clone.rs deleted file mode 100644 index fda94f9972..0000000000 --- a/tests/expectations/tests/derive-clone.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This struct should derive `Clone`. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ShouldDeriveClone { - pub large: [::std::os::raw::c_int; 33usize], -} -#[test] -fn bindgen_test_layout_ShouldDeriveClone() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(ShouldDeriveClone)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ShouldDeriveClone)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldDeriveClone), - "::", - stringify!(large) - ) - ); -} -impl Default for ShouldDeriveClone { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-clone_1_0.rs b/tests/expectations/tests/derive-clone_1_0.rs deleted file mode 100644 index c71eb92fa9..0000000000 --- a/tests/expectations/tests/derive-clone_1_0.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// Since builtin `Clone` impls were introduced in Rust 1.21 this struct -/// should impl `Clone` "manually". -#[repr(C)] -#[derive(Copy)] -pub struct ShouldImplClone { - pub large: [::std::os::raw::c_int; 33usize], -} -#[test] -fn bindgen_test_layout_ShouldImplClone() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(ShouldImplClone)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ShouldImplClone)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldImplClone), - "::", - stringify!(large) - ) - ); -} -impl Clone for ShouldImplClone { - fn clone(&self) -> Self { - *self - } -} -impl Default for ShouldImplClone { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-debug-bitfield.rs b/tests/expectations/tests/derive-debug-bitfield.rs deleted file mode 100644 index 3743b8d968..0000000000 --- a/tests/expectations/tests/derive-debug-bitfield.rs +++ /dev/null @@ -1,172 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct C { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub large_array: [::std::os::raw::c_int; 50usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 204usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large_array as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(large_array) - ) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for C { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!( - f, - "C {{ a : {:?}, b : {:?}, large_array: [{}] }}", - self.a(), - self.b(), - self.large_array - .iter() - .enumerate() - .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) - .collect::() - ) - } -} -impl C { - #[inline] - pub fn a(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_a(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } - } - #[inline] - pub fn set_b(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 7u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let a: u8 = unsafe { ::std::mem::transmute(a) }; - a as u64 - }); - __bindgen_bitfield_unit.set(1usize, 7u8, { - let b: u8 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/derive-debug-function-pointer.rs b/tests/expectations/tests/derive-debug-function-pointer.rs deleted file mode 100644 index c7aed70db3..0000000000 --- a/tests/expectations/tests/derive-debug-function-pointer.rs +++ /dev/null @@ -1,65 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Nice { - pub pointer: Nice_Function, - pub large_array: [::std::os::raw::c_int; 34usize], -} -pub type Nice_Function = ::std::option::Option; -#[test] -fn bindgen_test_layout_Nice() { - assert_eq!( - ::std::mem::size_of::(), - 144usize, - concat!("Size of: ", stringify!(Nice)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Nice)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pointer as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Nice), - "::", - stringify!(pointer) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large_array as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(Nice), - "::", - stringify!(large_array) - ) - ); -} -impl Default for Nice { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for Nice { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!( - f, - "Nice {{ pointer: {:?}, large_array: [{}] }}", - self.pointer, - self.large_array - .iter() - .enumerate() - .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) - .collect::() - ) - } -} diff --git a/tests/expectations/tests/derive-debug-generic.rs b/tests/expectations/tests/derive-debug-generic.rs deleted file mode 100644 index 6c0b41a67f..0000000000 --- a/tests/expectations/tests/derive-debug-generic.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct Generic { - pub t: [T; 40usize], - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Generic { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for Generic { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Generic {{ t: Array with length 40 }}") - } -} diff --git a/tests/expectations/tests/derive-debug-mangle-name.rs b/tests/expectations/tests/derive-debug-mangle-name.rs deleted file mode 100644 index acdcba108a..0000000000 --- a/tests/expectations/tests/derive-debug-mangle-name.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct perf_event_attr { - pub type_: ::std::os::raw::c_uint, - pub a: f32, - pub __bindgen_anon_1: perf_event_attr__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union perf_event_attr__bindgen_ty_1 { - pub b: ::std::os::raw::c_int, - pub c: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_perf_event_attr__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(perf_event_attr__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(perf_event_attr__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(perf_event_attr__bindgen_ty_1), - "::", - stringify!(b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(perf_event_attr__bindgen_ty_1), - "::", - stringify!(c) - ) - ); -} -impl Default for perf_event_attr__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for perf_event_attr__bindgen_ty_1 { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "perf_event_attr__bindgen_ty_1 {{ union }}") - } -} -#[test] -fn bindgen_test_layout_perf_event_attr() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(perf_event_attr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(perf_event_attr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(perf_event_attr), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(perf_event_attr), - "::", - stringify!(a) - ) - ); -} -impl Default for perf_event_attr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for perf_event_attr { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!( - f, - "perf_event_attr {{ type: {:?}, a: {:?}, __bindgen_anon_1: {:?} }}", - self.type_, - self.a, - self.__bindgen_anon_1 - ) - } -} diff --git a/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs b/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs deleted file mode 100644 index f323245e16..0000000000 --- a/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct Instance { - pub val: [u32; 50usize], -} -#[test] -fn bindgen_test_layout_Instance() { - assert_eq!( - ::std::mem::size_of::(), - 200usize, - concat!("Size of: ", stringify!(Instance)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Instance)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).val as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Instance), - "::", - stringify!(val) - ) - ); -} -impl Default for Instance { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for Instance { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Instance {{ val: opaque }}") - } -} diff --git a/tests/expectations/tests/derive-debug-opaque.rs b/tests/expectations/tests/derive-debug-opaque.rs deleted file mode 100644 index a18e210c7e..0000000000 --- a/tests/expectations/tests/derive-debug-opaque.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct Opaque { - pub _bindgen_opaque_blob: [u32; 41usize], -} -#[test] -fn bindgen_test_layout_Opaque() { - assert_eq!( - ::std::mem::size_of::(), - 164usize, - concat!("Size of: ", stringify!(Opaque)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Opaque)) - ); -} -impl Default for Opaque { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Opaque {{ opaque }}") - } -} -#[repr(C)] -pub struct OpaqueUser { - pub opaque: Opaque, -} -#[test] -fn bindgen_test_layout_OpaqueUser() { - assert_eq!( - ::std::mem::size_of::(), - 164usize, - concat!("Size of: ", stringify!(OpaqueUser)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(OpaqueUser)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).opaque as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(OpaqueUser), - "::", - stringify!(opaque) - ) - ); -} -impl Default for OpaqueUser { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::fmt::Debug for OpaqueUser { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "OpaqueUser {{ opaque: {:?} }}", self.opaque) - } -} diff --git a/tests/expectations/tests/derive-default-and-blacklist.rs b/tests/expectations/tests/derive-default-and-blacklist.rs deleted file mode 100644 index 7b1b1afca8..0000000000 --- a/tests/expectations/tests/derive-default-and-blacklist.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub struct BlacklistMe(u8); - - -/// Because this type contains a blacklisted type, it should not derive -/// Default. Instead, we should emit a `mem::zeroed` implementation. -#[repr(C)] -pub struct ShouldNotDeriveDefault { - pub a: BlacklistMe, -} -#[test] -fn bindgen_test_layout_ShouldNotDeriveDefault() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ShouldNotDeriveDefault)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ShouldNotDeriveDefault)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotDeriveDefault), - "::", - stringify!(a) - ) - ); -} -impl Default for ShouldNotDeriveDefault { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-fn-ptr.rs b/tests/expectations/tests/derive-fn-ptr.rs deleted file mode 100644 index 4b7105e97d..0000000000 --- a/tests/expectations/tests/derive-fn-ptr.rs +++ /dev/null @@ -1,108 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type my_fun_t = ::std::option::Option< - unsafe extern "C" fn( - arg1: ::std::os::raw::c_int, - arg2: ::std::os::raw::c_int, - arg3: ::std::os::raw::c_int, - arg4: ::std::os::raw::c_int, - arg5: ::std::os::raw::c_int, - arg6: ::std::os::raw::c_int, - arg7: ::std::os::raw::c_int, - arg8: ::std::os::raw::c_int, - arg9: ::std::os::raw::c_int, - arg10: ::std::os::raw::c_int, - arg11: ::std::os::raw::c_int, - arg12: ::std::os::raw::c_int, - arg13: ::std::os::raw::c_int, - arg14: ::std::os::raw::c_int, - arg15: ::std::os::raw::c_int, - arg16: ::std::os::raw::c_int, - ), ->; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Foo { - pub callback: my_fun_t, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).callback as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Foo), - "::", - stringify!(callback) - ) - ); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type my_fun2_t = ::std::option::Option< - unsafe extern "C" fn( - arg1: ::std::os::raw::c_int, - arg2: ::std::os::raw::c_int, - arg3: ::std::os::raw::c_int, - arg4: ::std::os::raw::c_int, - arg5: ::std::os::raw::c_int, - arg6: ::std::os::raw::c_int, - arg7: ::std::os::raw::c_int, - arg8: ::std::os::raw::c_int, - arg9: ::std::os::raw::c_int, - arg10: ::std::os::raw::c_int, - arg11: ::std::os::raw::c_int, - arg12: ::std::os::raw::c_int, - ), ->; -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Bar { - pub callback: my_fun2_t, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).callback as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(callback) - ) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-hash-and-blacklist.rs b/tests/expectations/tests/derive-hash-and-blacklist.rs deleted file mode 100644 index ef12b9a8ab..0000000000 --- a/tests/expectations/tests/derive-hash-and-blacklist.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub struct BlacklistMe(u8); - - -/// Because this type contains a blacklisted type, it should not derive Hash. -#[repr(C)] -pub struct ShouldNotDeriveHash { - pub a: BlacklistMe, -} -#[test] -fn bindgen_test_layout_ShouldNotDeriveHash() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ShouldNotDeriveHash)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ShouldNotDeriveHash)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotDeriveHash), - "::", - stringify!(a) - ) - ); -} -impl Default for ShouldNotDeriveHash { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-hash-blacklisting.rs b/tests/expectations/tests/derive-hash-blacklisting.rs deleted file mode 100644 index fa35d6ca54..0000000000 --- a/tests/expectations/tests/derive-hash-blacklisting.rs +++ /dev/null @@ -1,80 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] -pub struct Blacklisted { - t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} - - -/// This would derive(Hash, Eq, PartialEq) if it didn't contain a blacklisted type, -/// causing us to conservatively avoid deriving hash/Eq/PartialEq for it. -#[repr(C)] -pub struct WhitelistedOne { - pub a: Blacklisted<::std::os::raw::c_int>, -} -#[test] -fn bindgen_test_layout_WhitelistedOne() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WhitelistedOne)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WhitelistedOne)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WhitelistedOne), - "::", - stringify!(a) - ) - ); -} -impl Default for WhitelistedOne { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// This can't derive(Hash/Eq) even if it didn't contain a blacklisted type. -#[repr(C)] -pub struct WhitelistedTwo { - pub b: Blacklisted, -} -#[test] -fn bindgen_test_layout_WhitelistedTwo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WhitelistedTwo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WhitelistedTwo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WhitelistedTwo), - "::", - stringify!(b) - ) - ); -} -impl Default for WhitelistedTwo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs b/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs deleted file mode 100644 index 11c86de473..0000000000 --- a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// A struct containing a struct containing a float that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] -pub struct foo__bindgen_ty_1 { - pub a: f32, - pub b: f32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/derive-hash-struct-with-float-array.rs b/tests/expectations/tests/derive-hash-struct-with-float-array.rs deleted file mode 100644 index 12ac57aabc..0000000000 --- a/tests/expectations/tests/derive-hash-struct-with-float-array.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// A struct containing an array of floats that cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq)] -pub struct foo { - pub bar: [f32; 3usize], -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs b/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs deleted file mode 100644 index 7f56de7bfe..0000000000 --- a/tests/expectations/tests/derive-hash-struct-with-incomplete-array.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -#[repr(C)] -#[derive(Debug, Default)] -pub struct test { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_test() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(test), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).zero_length_array as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(test), - "::", - stringify!(zero_length_array) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct test2 { - pub a: ::std::os::raw::c_int, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_test2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(test2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(test2)) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct test3 { - pub a: ::std::os::raw::c_int, - pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>, - pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_test3() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(test3)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(test3)) - ); -} diff --git a/tests/expectations/tests/derive-hash-struct-with-pointer.rs b/tests/expectations/tests/derive-hash-struct-with-pointer.rs deleted file mode 100644 index ee41c4f4f4..0000000000 --- a/tests/expectations/tests/derive-hash-struct-with-pointer.rs +++ /dev/null @@ -1,140 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// Pointers can derive Hash/PartialOrd/Ord/PartialEq/Eq -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct ConstPtrMutObj { - pub bar: *const ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ConstPtrMutObj() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ConstPtrMutObj)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ConstPtrMutObj)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ConstPtrMutObj), - "::", - stringify!(bar) - ) - ); -} -impl Default for ConstPtrMutObj { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct MutPtrMutObj { - pub bar: *mut ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_MutPtrMutObj() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(MutPtrMutObj)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(MutPtrMutObj)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(MutPtrMutObj), - "::", - stringify!(bar) - ) - ); -} -impl Default for MutPtrMutObj { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct MutPtrConstObj { - pub bar: *const ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_MutPtrConstObj() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(MutPtrConstObj)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(MutPtrConstObj)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(MutPtrConstObj), - "::", - stringify!(bar) - ) - ); -} -impl Default for MutPtrConstObj { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct ConstPtrConstObj { - pub bar: *const ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ConstPtrConstObj() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ConstPtrConstObj)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ConstPtrConstObj)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ConstPtrConstObj), - "::", - stringify!(bar) - ) - ); -} -impl Default for ConstPtrConstObj { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-hash-template-def-float.rs b/tests/expectations/tests/derive-hash-template-def-float.rs deleted file mode 100644 index 853d77affe..0000000000 --- a/tests/expectations/tests/derive-hash-template-def-float.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// Template definition containing a float, which cannot derive Hash/Eq/Ord but can derive PartialEq/PartialOrd. -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] -pub struct foo { - pub data: T, - pub b: f32, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-hash-template-inst-float.rs b/tests/expectations/tests/derive-hash-template-inst-float.rs deleted file mode 100644 index abb98f0515..0000000000 --- a/tests/expectations/tests/derive-hash-template-inst-float.rs +++ /dev/null @@ -1,117 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// Template definition that doesn't contain float can derive Hash/PartialOrd/Ord/PartialEq/Eq -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct foo { - pub data: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// Can derive Hash/PartialOrd/Ord/PartialEq/Eq when instantiated with int -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct IntStr { - pub a: foo<::std::os::raw::c_int>, -} -#[test] -fn bindgen_test_layout_IntStr() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(IntStr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(IntStr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(IntStr), "::", stringify!(a)) - ); -} -impl Default for IntStr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// Cannot derive Hash/Eq/Ord when instantiated with float but can derive PartialEq/PartialOrd -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] -pub struct FloatStr { - pub a: foo, -} -#[test] -fn bindgen_test_layout_FloatStr() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(FloatStr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(FloatStr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(FloatStr), - "::", - stringify!(a) - ) - ); -} -impl Default for FloatStr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_foo_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(foo<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(foo<::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_foo_open0_float_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!("Size of template specialization: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(foo) - ) - ); -} diff --git a/tests/expectations/tests/derive-partialeq-and-blacklist.rs b/tests/expectations/tests/derive-partialeq-and-blacklist.rs deleted file mode 100644 index 1c51c3a395..0000000000 --- a/tests/expectations/tests/derive-partialeq-and-blacklist.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub struct BlacklistMe(u8); - - -/// Because this type contains a blacklisted type, it should not derive -/// PartialEq. -#[repr(C)] -pub struct ShouldNotDerivePartialEq { - pub a: BlacklistMe, -} -#[test] -fn bindgen_test_layout_ShouldNotDerivePartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ShouldNotDerivePartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ShouldNotDerivePartialEq)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotDerivePartialEq), - "::", - stringify!(a) - ) - ); -} -impl Default for ShouldNotDerivePartialEq { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-partialeq-anonfield.rs b/tests/expectations/tests/derive-partialeq-anonfield.rs deleted file mode 100644 index 73972d70d7..0000000000 --- a/tests/expectations/tests/derive-partialeq-anonfield.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_mbuf { - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_1 { - _bindgen_union_align: [u8; 0usize], -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_1)) - ); -} -impl Default for rte_mbuf__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_mbuf() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(rte_mbuf)) - ); -} -impl Default for rte_mbuf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-partialeq-base.rs b/tests/expectations/tests/derive-partialeq-base.rs deleted file mode 100644 index ed92813b5d..0000000000 --- a/tests/expectations/tests/derive-partialeq-base.rs +++ /dev/null @@ -1,72 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Base { - pub large: [::std::os::raw::c_int; 33usize], -} -#[test] -fn bindgen_test_layout_Base() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(Base)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Base)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Base), - "::", - stringify!(large) - ) - ); -} -impl Default for Base { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for Base { - fn eq(&self, other: &Base) -> bool { - &self.large[..] == &other.large[..] - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ShouldDerivePartialEq { - pub _base: Base, -} -#[test] -fn bindgen_test_layout_ShouldDerivePartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(ShouldDerivePartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ShouldDerivePartialEq)) - ); -} -impl Default for ShouldDerivePartialEq { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for ShouldDerivePartialEq { - fn eq(&self, other: &ShouldDerivePartialEq) -> bool { - self._base == other._base - } -} diff --git a/tests/expectations/tests/derive-partialeq-bitfield.rs b/tests/expectations/tests/derive-partialeq-bitfield.rs deleted file mode 100644 index a3715b0cc7..0000000000 --- a/tests/expectations/tests/derive-partialeq-bitfield.rs +++ /dev/null @@ -1,163 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct C { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub large_array: [::std::os::raw::c_int; 50usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 204usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large_array as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(large_array) - ) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for C { - fn eq(&self, other: &C) -> bool { - self.a() == other.a() && self.b() == other.b() - && &self.large_array[..] == &other.large_array[..] - } -} -impl C { - #[inline] - pub fn a(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_a(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } - } - #[inline] - pub fn set_b(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 7u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let a: u8 = unsafe { ::std::mem::transmute(a) }; - a as u64 - }); - __bindgen_bitfield_unit.set(1usize, 7u8, { - let b: u8 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/derive-partialeq-core.rs b/tests/expectations/tests/derive-partialeq-core.rs deleted file mode 100644 index 7d6f35719a..0000000000 --- a/tests/expectations/tests/derive-partialeq-core.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -extern crate core; - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct C { - pub large_array: [::std::os::raw::c_int; 420usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::core::mem::size_of::(), - 1680usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::core::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).large_array as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(large_array) - ) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } -} -impl ::core::cmp::PartialEq for C { - fn eq(&self, other: &C) -> bool { - &self.large_array[..] == &other.large_array[..] - } -} diff --git a/tests/expectations/tests/derive-partialeq-pointer.rs b/tests/expectations/tests/derive-partialeq-pointer.rs deleted file mode 100644 index 4ce1a3fe3f..0000000000 --- a/tests/expectations/tests/derive-partialeq-pointer.rs +++ /dev/null @@ -1,109 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Bar { - pub b: *mut a, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(b)) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct c { - pub __bindgen_anon_1: c__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union c__bindgen_ty_1 { - _bindgen_union_align: u8, - pub _address: u8, -} -#[test] -fn bindgen_test_layout_c__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(c__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(c__bindgen_ty_1)) - ); -} -impl Default for c__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_c() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(c)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(c)) - ); -} -impl Default for c { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct a { - pub d: c, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::
(), - 1usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(d)) - ); -} -impl Default for a { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-partialeq-union.rs b/tests/expectations/tests/derive-partialeq-union.rs deleted file mode 100644 index 68344591a3..0000000000 --- a/tests/expectations/tests/derive-partialeq-union.rs +++ /dev/null @@ -1,53 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// Deriving PartialEq for rust unions is not supported. -#[repr(C)] -#[derive(Copy, Clone)] -pub union ShouldNotDerivePartialEq { - pub a: ::std::os::raw::c_char, - pub b: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_ShouldNotDerivePartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(ShouldNotDerivePartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ShouldNotDerivePartialEq)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotDerivePartialEq), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotDerivePartialEq), - "::", - stringify!(b) - ) - ); -} -impl Default for ShouldNotDerivePartialEq { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/derive-partialeq-union_1_0.rs b/tests/expectations/tests/derive-partialeq-union_1_0.rs deleted file mode 100644 index dab82854ec..0000000000 --- a/tests/expectations/tests/derive-partialeq-union_1_0.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -/// This should manually derive PartialEq. -#[repr(C)] -#[derive(Copy)] -pub struct ShouldDerivePartialEq { - pub a: __BindgenUnionField<[::std::os::raw::c_char; 150usize]>, - pub b: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: [u32; 38usize], -} -#[test] -fn bindgen_test_layout_ShouldDerivePartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 152usize, - concat!("Size of: ", stringify!(ShouldDerivePartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ShouldDerivePartialEq)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldDerivePartialEq), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldDerivePartialEq), - "::", - stringify!(b) - ) - ); -} -impl Clone for ShouldDerivePartialEq { - fn clone(&self) -> Self { - *self - } -} -impl Default for ShouldDerivePartialEq { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for ShouldDerivePartialEq { - fn eq(&self, other: &ShouldDerivePartialEq) -> bool { - &self.bindgen_union_field[..] == &other.bindgen_union_field[..] - } -} diff --git a/tests/expectations/tests/disable-namespacing.rs b/tests/expectations/tests/disable-namespacing.rs deleted file mode 100644 index b369a22dfd..0000000000 --- a/tests/expectations/tests/disable-namespacing.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type Baz = ::std::os::raw::c_int; diff --git a/tests/expectations/tests/divide-by-zero-in-struct-layout.rs b/tests/expectations/tests/divide-by-zero-in-struct-layout.rs deleted file mode 100644 index 9709332180..0000000000 --- a/tests/expectations/tests/divide-by-zero-in-struct-layout.rs +++ /dev/null @@ -1,130 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct WithBitfield { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 0usize], u8>, - pub __bindgen_padding_0: u32, - pub a: ::std::os::raw::c_uint, -} -impl WithBitfield { - #[inline] - pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 0usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 0usize], u8> = - Default::default(); - __bindgen_bitfield_unit - } -} -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct WithBitfieldAndAttrPacked { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 0usize], u8>, - pub a: ::std::os::raw::c_uint, - pub __bindgen_padding_0: u8, -} -impl WithBitfieldAndAttrPacked { - #[inline] - pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 0usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 0usize], u8> = - Default::default(); - __bindgen_bitfield_unit - } -} -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct WithBitfieldAndPacked { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 0usize], u8>, - pub a: ::std::os::raw::c_uint, - pub __bindgen_padding_0: u8, -} -impl WithBitfieldAndPacked { - #[inline] - pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 0usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 0usize], u8> = - Default::default(); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/do-not-derive-copy.rs b/tests/expectations/tests/do-not-derive-copy.rs deleted file mode 100644 index 50fcebd415..0000000000 --- a/tests/expectations/tests/do-not-derive-copy.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct WouldBeCopyButWeAreNotDerivingCopy { - pub x: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_WouldBeCopyButWeAreNotDerivingCopy() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(WouldBeCopyButWeAreNotDerivingCopy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(WouldBeCopyButWeAreNotDerivingCopy) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).x as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WouldBeCopyButWeAreNotDerivingCopy), - "::", - stringify!(x) - ) - ); -} diff --git a/tests/expectations/tests/doggo-or-null.rs b/tests/expectations/tests/doggo-or-null.rs deleted file mode 100644 index cf576634ce..0000000000 --- a/tests/expectations/tests/doggo-or-null.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq)] -pub struct Doggo { - pub x: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Doggo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Doggo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Doggo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Doggo), "::", stringify!(x)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq)] -pub struct Null { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Null() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Null)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Null)) - ); -} -/// This type is an opaque union. Unions can't derive anything interesting like -/// Debug or Default, even if their layout can, because it would require knowing -/// which variant is in use. Opaque unions still end up as a `union` in the Rust -/// bindings, but they just have one variant. Even so, can't derive. We should -/// probably emit an opaque struct for opaque unions... but until then, we have -/// this test to make sure that opaque unions don't derive and still compile. -#[repr(C)] -#[derive(Copy, Clone)] -pub union DoggoOrNull { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_DoggoOrNull() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(DoggoOrNull)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(DoggoOrNull)) - ); -} -impl Default for DoggoOrNull { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/duplicated-namespaces-definitions.rs b/tests/expectations/tests/duplicated-namespaces-definitions.rs deleted file mode 100644 index fff400c2b8..0000000000 --- a/tests/expectations/tests/duplicated-namespaces-definitions.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod foo { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar { - pub foo: ::std::os::raw::c_int, - pub baz: bool, - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz)) - ); - } - } - pub mod bar { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Foo { - pub ptr: *mut root::foo::Bar, - } - #[test] - fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(ptr)) - ); - } - impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - } -} diff --git a/tests/expectations/tests/empty-enum.rs b/tests/expectations/tests/empty-enum.rs deleted file mode 100644 index 473a508ad4..0000000000 --- a/tests/expectations/tests/empty-enum.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub type EmptyConstified = u32; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum EmptyRustified { - __bindgen_cannot_repr_c_on_empty_enum = 0, -} -pub mod EmptyModule { - pub type Type = u32; -} -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum EmptyClassRustified { - __bindgen_cannot_repr_c_on_empty_enum = 0, -} -pub type EmptyClassConstified = i8; -pub mod EmptyClassModule { - pub type Type = i8; -} -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum ForwardClassRustified { - __bindgen_cannot_repr_c_on_empty_enum = 0, -} -pub type ForwardClassConstified = i8; -pub mod ForwardClassModule { - pub type Type = i8; -} diff --git a/tests/expectations/tests/enum-doc-bitfield.rs b/tests/expectations/tests/enum-doc-bitfield.rs deleted file mode 100644 index 93d1f5f080..0000000000 --- a/tests/expectations/tests/enum-doc-bitfield.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -impl B { - /// Document field with three slashes - pub const VAR_A: B = B(0); -} -impl B { - /// Document field with preceeding star - pub const VAR_B: B = B(1); -} -impl B { - /// Document field with preceeding exclamation - pub const VAR_C: B = B(2); -} -impl B { - /// < Document field with following star - pub const VAR_D: B = B(3); -} -impl B { - /// < Document field with following exclamation - pub const VAR_E: B = B(4); -} -impl B { - /// Document field with preceeding star, with a loong long multiline - /// comment. - /// - /// Very interesting documentation, definitely. - pub const VAR_F: B = B(5); -} -impl ::std::ops::BitOr for B { - type Output = Self; - #[inline] - fn bitor(self, other: Self) -> Self { - B(self.0 | other.0) - } -} -impl ::std::ops::BitOrAssign for B { - #[inline] - fn bitor_assign(&mut self, rhs: B) { - self.0 |= rhs.0; - } -} -impl ::std::ops::BitAnd for B { - type Output = Self; - #[inline] - fn bitand(self, other: Self) -> Self { - B(self.0 & other.0) - } -} -impl ::std::ops::BitAndAssign for B { - #[inline] - fn bitand_assign(&mut self, rhs: B) { - self.0 &= rhs.0; - } -} -#[repr(C)] -/// Document enum -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct B(pub u32); diff --git a/tests/expectations/tests/enum-doc-mod.rs b/tests/expectations/tests/enum-doc-mod.rs deleted file mode 100644 index cb10bb3d6d..0000000000 --- a/tests/expectations/tests/enum-doc-mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod B { - /// Document enum - pub type Type = u32; - /// Document field with three slashes - pub const VAR_A: Type = 0; - /// Document field with preceeding star - pub const VAR_B: Type = 1; - /// Document field with preceeding exclamation - pub const VAR_C: Type = 2; - /// < Document field with following star - pub const VAR_D: Type = 3; - /// < Document field with following exclamation - pub const VAR_E: Type = 4; - /// Document field with preceeding star, with a loong long multiline - /// comment. - /// - /// Very interesting documentation, definitely. - pub const VAR_F: Type = 5; -} diff --git a/tests/expectations/tests/enum-doc-rusty.rs b/tests/expectations/tests/enum-doc-rusty.rs deleted file mode 100644 index 2a57fb6436..0000000000 --- a/tests/expectations/tests/enum-doc-rusty.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u32)] -/// Document enum -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum B { - /// Document field with three slashes - VAR_A = 0, - /// Document field with preceeding star - VAR_B = 1, - /// Document field with preceeding exclamation - VAR_C = 2, - /// < Document field with following star - VAR_D = 3, - /// < Document field with following exclamation - VAR_E = 4, - /// Document field with preceeding star, with a loong long multiline - /// comment. - /// - /// Very interesting documentation, definitely. - VAR_F = 5, -} diff --git a/tests/expectations/tests/enum-doc.rs b/tests/expectations/tests/enum-doc.rs deleted file mode 100644 index e57728fb4f..0000000000 --- a/tests/expectations/tests/enum-doc.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -/// Document field with three slashes -pub const B_VAR_A: B = 0; -/// Document field with preceeding star -pub const B_VAR_B: B = 1; -/// Document field with preceeding exclamation -pub const B_VAR_C: B = 2; -/// < Document field with following star -pub const B_VAR_D: B = 3; -/// < Document field with following exclamation -pub const B_VAR_E: B = 4; -/// Document field with preceeding star, with a loong long multiline -/// comment. -/// -/// Very interesting documentation, definitely. -pub const B_VAR_F: B = 5; -/// Document enum -pub type B = u32; diff --git a/tests/expectations/tests/enum-variant-replaces.rs b/tests/expectations/tests/enum-variant-replaces.rs deleted file mode 100644 index aabcad753f..0000000000 --- a/tests/expectations/tests/enum-variant-replaces.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -///
-/// -/// Should see PASS below. -pub const OGRErr_PASS: OGRErr = 0; -///
-/// -/// Should see OGRERR_NONE instead of CUSTOM_OGRERR_NONE below. -pub const OGRErr_OGRERR_NONE: OGRErr = 1; -///
-pub type OGRErr = u32; diff --git a/tests/expectations/tests/enum.rs b/tests/expectations/tests/enum.rs deleted file mode 100644 index 2ed5d18778..0000000000 --- a/tests/expectations/tests/enum.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - Bar = 0, - Qux = 1, -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { - MinusOne = -1, - One = 1, -} diff --git a/tests/expectations/tests/enum_alias.rs b/tests/expectations/tests/enum_alias.rs deleted file mode 100644 index 30a4f62a8d..0000000000 --- a/tests/expectations/tests/enum_alias.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bar { - VAL = 0, -} diff --git a/tests/expectations/tests/enum_and_vtable_mangling.rs b/tests/expectations/tests/enum_and_vtable_mangling.rs deleted file mode 100644 index 76e28aaf70..0000000000 --- a/tests/expectations/tests/enum_and_vtable_mangling.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_; -pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - match_ = 0, - whatever_else = 1, -} -#[repr(C)] -pub struct C__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct C { - pub vtable_: *const C__bindgen_vtable, - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(i)) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN1C5matchEv"] - pub fn C_match(this: *mut ::std::os::raw::c_void); -} diff --git a/tests/expectations/tests/enum_dupe.rs b/tests/expectations/tests/enum_dupe.rs deleted file mode 100644 index 29bd7502a4..0000000000 --- a/tests/expectations/tests/enum_dupe.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const Foo_Dupe: Foo = Foo::Bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - Bar = 1, -} diff --git a/tests/expectations/tests/enum_explicit_type.rs b/tests/expectations/tests/enum_explicit_type.rs deleted file mode 100644 index a5ec4a57b7..0000000000 --- a/tests/expectations/tests/enum_explicit_type.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - Bar = 0, - Qux = 1, -} -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { - MinusOne = -1, - One = 1, -} -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bigger { - Much = 255, - Larger = 256, -} -#[repr(i64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchLong { - MuchLow = -4294967296, -} -#[repr(i64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchLongLong { - I64_MIN = -9223372036854775808, -} -#[repr(u64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchULongLong { - MuchHigh = 4294967296, -} -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum BoolEnumsAreFun { - Value = 1, -} diff --git a/tests/expectations/tests/enum_explicit_type_constants.rs b/tests/expectations/tests/enum_explicit_type_constants.rs deleted file mode 100644 index cd1a922903..0000000000 --- a/tests/expectations/tests/enum_explicit_type_constants.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const Foo_Bar: Foo = 0; -pub const Foo_Qux: Foo = 1; -pub type Foo = u8; -pub const Neg_MinusOne: Neg = -1; -pub const Neg_One: Neg = 1; -pub type Neg = i8; -pub const Bigger_Much: Bigger = 255; -pub const Bigger_Larger: Bigger = 256; -pub type Bigger = u16; -pub const MuchLong_MuchLow: MuchLong = -4294967296; -pub type MuchLong = i64; -pub const MuchLongLong_I64_MIN: MuchLongLong = -9223372036854775808; -pub type MuchLongLong = i64; -pub const MuchULongLong_MuchHigh: MuchULongLong = 4294967296; -pub type MuchULongLong = u64; -pub const BoolEnumsAreFun_Value: BoolEnumsAreFun = 1; -pub type BoolEnumsAreFun = u8; diff --git a/tests/expectations/tests/enum_in_template_with_typedef.rs b/tests/expectations/tests/enum_in_template_with_typedef.rs deleted file mode 100644 index a3b4e7762f..0000000000 --- a/tests/expectations/tests/enum_in_template_with_typedef.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct std_fbstring_core { - pub _address: u8, -} -pub type std_fbstring_core_category_type = u8; -pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category = - std_fbstring_core_Category::Foo; -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum std_fbstring_core_Category { - Foo = 0, -} diff --git a/tests/expectations/tests/enum_negative.rs b/tests/expectations/tests/enum_negative.rs deleted file mode 100644 index e066968db4..0000000000 --- a/tests/expectations/tests/enum_negative.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - Bar = -2, - Qux = 1, -} diff --git a/tests/expectations/tests/enum_packed.rs b/tests/expectations/tests/enum_packed.rs deleted file mode 100644 index d388b5edc0..0000000000 --- a/tests/expectations/tests/enum_packed.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - Bar = 0, - Qux = 1, -} -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { - MinusOne = -1, - One = 1, -} -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bigger { - Much = 255, - Larger = 256, -} diff --git a/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs deleted file mode 100644 index 9613a7f2e2..0000000000 --- a/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const a: u32 = 18446744073709551611; diff --git a/tests/expectations/tests/extern.rs b/tests/expectations/tests/extern.rs deleted file mode 100644 index e257b7bca4..0000000000 --- a/tests/expectations/tests/extern.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type foo = ::std::option::Option< - unsafe extern "C" fn(bar: ::std::os::raw::c_int) - -> ::std::os::raw::c_int, ->; diff --git a/tests/expectations/tests/float128.rs b/tests/expectations/tests/float128.rs deleted file mode 100644 index 5dcc6c4008..0000000000 --- a/tests/expectations/tests/float128.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] diff --git a/tests/expectations/tests/forward-declaration-autoptr.rs b/tests/expectations/tests/forward-declaration-autoptr.rs deleted file mode 100644 index 5d3c3eaafb..0000000000 --- a/tests/expectations/tests/forward-declaration-autoptr.rs +++ /dev/null @@ -1,69 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RefPtr { - pub m_inner: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for RefPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Bar { - pub m_member: RefPtr, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(m_member) - ) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_RefPtr_open0_Foo_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!("Size of template specialization: ", stringify!(RefPtr)) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(RefPtr) - ) - ); -} diff --git a/tests/expectations/tests/forward-enum-decl.rs b/tests/expectations/tests/forward-enum-decl.rs deleted file mode 100644 index d327cb725b..0000000000 --- a/tests/expectations/tests/forward-enum-decl.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum CSSPseudoClassType { - empty = 0, - link = 1, -} diff --git a/tests/expectations/tests/forward-inherit-struct-with-fields.rs b/tests/expectations/tests/forward-inherit-struct-with-fields.rs deleted file mode 100644 index 19772dbe06..0000000000 --- a/tests/expectations/tests/forward-inherit-struct-with-fields.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct js_RootedBase { - pub foo: *mut T, - pub next: *mut Rooted, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for js_RootedBase { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _base: js_RootedBase, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/forward-inherit-struct.rs b/tests/expectations/tests/forward-inherit-struct.rs deleted file mode 100644 index a2399bcb7c..0000000000 --- a/tests/expectations/tests/forward-inherit-struct.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct js_RootedBase { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _address: u8, -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/forward_declared_complex_types.rs b/tests/expectations/tests/forward_declared_complex_types.rs deleted file mode 100644 index 1132bfbe89..0000000000 --- a/tests/expectations/tests/forward_declared_complex_types.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo_empty { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo_empty() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo_empty)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo_empty)) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Bar { - pub f: *mut Foo, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(f)) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z10baz_structP3Foo"] - pub fn baz_struct(f: *mut Foo); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Union { - _unused: [u8; 0], -} -extern "C" { - #[link_name = "\u{1}_Z9baz_unionP5Union"] - pub fn baz_union(u: *mut Union); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Quux { - _unused: [u8; 0], -} -extern "C" { - #[link_name = "\u{1}_Z9baz_classP4Quux"] - pub fn baz_class(q: *mut Quux); -} diff --git a/tests/expectations/tests/forward_declared_complex_types_1_0.rs b/tests/expectations/tests/forward_declared_complex_types_1_0.rs deleted file mode 100644 index 0a6a32be81..0000000000 --- a/tests/expectations/tests/forward_declared_complex_types_1_0.rs +++ /dev/null @@ -1,102 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy)] -pub struct Foo_empty { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo_empty() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo_empty)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo_empty)) - ); -} -impl Clone for Foo_empty { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Foo { - _unused: [u8; 0], -} -impl Clone for Foo { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Bar { - pub f: *mut Foo, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(f)) - ); -} -impl Clone for Bar { - fn clone(&self) -> Self { - *self - } -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z10baz_structP3Foo"] - pub fn baz_struct(f: *mut Foo); -} -#[repr(C)] -#[derive(Copy)] -pub struct Union { - _unused: [u8; 0], -} -impl Clone for Union { - fn clone(&self) -> Self { - *self - } -} -extern "C" { - #[link_name = "\u{1}_Z9baz_unionP5Union"] - pub fn baz_union(u: *mut Union); -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Quux { - _unused: [u8; 0], -} -impl Clone for Quux { - fn clone(&self) -> Self { - *self - } -} -extern "C" { - #[link_name = "\u{1}_Z9baz_classP4Quux"] - pub fn baz_class(q: *mut Quux); -} diff --git a/tests/expectations/tests/forward_declared_struct.rs b/tests/expectations/tests/forward_declared_struct.rs deleted file mode 100644 index c69960b829..0000000000 --- a/tests/expectations/tests/forward_declared_struct.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct a { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::
(), - 4usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(b)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct c { - pub d: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_c() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(c)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(c)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(c), "::", stringify!(d)) - ); -} diff --git a/tests/expectations/tests/func_proto.rs b/tests/expectations/tests/func_proto.rs deleted file mode 100644 index e257b7bca4..0000000000 --- a/tests/expectations/tests/func_proto.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type foo = ::std::option::Option< - unsafe extern "C" fn(bar: ::std::os::raw::c_int) - -> ::std::os::raw::c_int, ->; diff --git a/tests/expectations/tests/func_ptr.rs b/tests/expectations/tests/func_ptr.rs deleted file mode 100644 index 730849c059..0000000000 --- a/tests/expectations/tests/func_ptr.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}foo"] - pub static mut foo: - ::std::option::Option< - unsafe extern "C" fn(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) - -> ::std::os::raw::c_int, - >; -} diff --git a/tests/expectations/tests/func_ptr_in_struct.rs b/tests/expectations/tests/func_ptr_in_struct.rs deleted file mode 100644 index d66ce84d1d..0000000000 --- a/tests/expectations/tests/func_ptr_in_struct.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum baz { - __bindgen_cannot_repr_c_on_empty_enum = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Foo { - pub bar: ::std::option::Option< - unsafe extern "C" fn(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) -> baz, - >, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar)) - ); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/func_with_array_arg.rs b/tests/expectations/tests/func_with_array_arg.rs deleted file mode 100644 index ec5617dcc7..0000000000 --- a/tests/expectations/tests/func_with_array_arg.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn f(x: *mut ::std::os::raw::c_int); -} diff --git a/tests/expectations/tests/func_with_func_ptr_arg.rs b/tests/expectations/tests/func_with_func_ptr_arg.rs deleted file mode 100644 index fed557b816..0000000000 --- a/tests/expectations/tests/func_with_func_ptr_arg.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(bar: ::std::option::Option); -} diff --git a/tests/expectations/tests/gen-constructors-neg.rs b/tests/expectations/tests/gen-constructors-neg.rs deleted file mode 100644 index 36cae7222f..0000000000 --- a/tests/expectations/tests/gen-constructors-neg.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/gen-constructors.rs b/tests/expectations/tests/gen-constructors.rs deleted file mode 100644 index cb2024a16b..0000000000 --- a/tests/expectations/tests/gen-constructors.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3FooC1Ei"] - pub fn Foo_Foo(this: *mut Foo, a: ::std::os::raw::c_int); -} -impl Foo { - #[inline] - pub unsafe fn new(a: ::std::os::raw::c_int) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - Foo_Foo(&mut __bindgen_tmp, a); - __bindgen_tmp - } -} diff --git a/tests/expectations/tests/gen-destructors-neg.rs b/tests/expectations/tests/gen-destructors-neg.rs deleted file mode 100644 index 37740e0970..0000000000 --- a/tests/expectations/tests/gen-destructors-neg.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct Foo { - pub bar: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/gen-destructors.rs b/tests/expectations/tests/gen-destructors.rs deleted file mode 100644 index 03ccec2ae6..0000000000 --- a/tests/expectations/tests/gen-destructors.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct Foo { - pub bar: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3FooD1Ev"] - pub fn Foo_Foo_destructor(this: *mut Foo); -} -impl Foo { - #[inline] - pub unsafe fn destruct(&mut self) { - Foo_Foo_destructor(self) - } -} diff --git a/tests/expectations/tests/generate-inline.rs b/tests/expectations/tests/generate-inline.rs deleted file mode 100644 index 48d8f4f898..0000000000 --- a/tests/expectations/tests/generate-inline.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo3barEv"] - pub fn Foo_bar() -> ::std::os::raw::c_int; -} -impl Foo { - #[inline] - pub unsafe fn bar() -> ::std::os::raw::c_int { - Foo_bar() - } -} -extern "C" { - #[link_name = "\u{1}_Z3foov"] - pub fn foo() -> ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/infinite-macro.rs b/tests/expectations/tests/infinite-macro.rs deleted file mode 100644 index 7c88ce2a52..0000000000 --- a/tests/expectations/tests/infinite-macro.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const INFINITY: f64 = ::std::f64::INFINITY; -pub const NAN: f64 = ::std::f64::NAN; diff --git a/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs b/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs deleted file mode 100644 index cf8b283c4b..0000000000 --- a/tests/expectations/tests/inherit-from-template-instantiation-with-vtable.rs +++ /dev/null @@ -1,208 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct BaseWithVtable__bindgen_vtable(::std::os::raw::c_void); -/// This should have an explicit vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct BaseWithVtable { - pub vtable_: *const BaseWithVtable__bindgen_vtable, - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for BaseWithVtable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// This should not have an explicit vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DerivedWithNoVirtualMethods { - pub _base: BaseWithVtable<*mut ::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_DerivedWithNoVirtualMethods() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(DerivedWithNoVirtualMethods)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(DerivedWithNoVirtualMethods)) - ); -} -impl Default for DerivedWithNoVirtualMethods { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// This should not have an explicit vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DerivedWithVirtualMethods { - pub _base: BaseWithVtable<*mut ::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_DerivedWithVirtualMethods() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(DerivedWithVirtualMethods)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(DerivedWithVirtualMethods)) - ); -} -impl Default for DerivedWithVirtualMethods { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// This should not have any vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct BaseWithoutVtable { - pub u: U, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for BaseWithoutVtable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct DerivedWithVtable__bindgen_vtable(::std::os::raw::c_void); -/// This should have an explicit vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DerivedWithVtable { - pub vtable_: *const DerivedWithVtable__bindgen_vtable, - pub _base: BaseWithoutVtable<*mut ::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_DerivedWithVtable() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(DerivedWithVtable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(DerivedWithVtable)) - ); -} -impl Default for DerivedWithVtable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// This should not have any vtable. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DerivedWithoutVtable { - pub _base: BaseWithoutVtable<*mut ::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_DerivedWithoutVtable() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(DerivedWithoutVtable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(DerivedWithoutVtable)) - ); -} -impl Default for DerivedWithoutVtable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_BaseWithVtable_open0_ptr_char_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 16usize, - concat!( - "Size of template specialization: ", - stringify!(BaseWithVtable<*mut ::std::os::raw::c_char>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(BaseWithVtable<*mut ::std::os::raw::c_char>) - ) - ); -} -#[test] -fn __bindgen_test_layout_BaseWithVtable_open0_ptr_char_close0_instantiation_1() { - assert_eq!( - ::std::mem::size_of::>(), - 16usize, - concat!( - "Size of template specialization: ", - stringify!(BaseWithVtable<*mut ::std::os::raw::c_char>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(BaseWithVtable<*mut ::std::os::raw::c_char>) - ) - ); -} -#[test] -fn __bindgen_test_layout_BaseWithoutVtable_open0_ptr_char_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(BaseWithoutVtable<*mut ::std::os::raw::c_char>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(BaseWithoutVtable<*mut ::std::os::raw::c_char>) - ) - ); -} -#[test] -fn __bindgen_test_layout_BaseWithoutVtable_open0_ptr_char_close0_instantiation_1() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(BaseWithoutVtable<*mut ::std::os::raw::c_char>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(BaseWithoutVtable<*mut ::std::os::raw::c_char>) - ) - ); -} diff --git a/tests/expectations/tests/inherit-namespaced.rs b/tests/expectations/tests/inherit-namespaced.rs deleted file mode 100644 index a2399bcb7c..0000000000 --- a/tests/expectations/tests/inherit-namespaced.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct js_RootedBase { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _address: u8, -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/inherit_named.rs b/tests/expectations/tests/inherit_named.rs deleted file mode 100644 index fadf270ebf..0000000000 --- a/tests/expectations/tests/inherit_named.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Wohoo { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Weeee { - pub _base: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Weeee { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/inherit_typedef.rs b/tests/expectations/tests/inherit_typedef.rs deleted file mode 100644 index 49e842d7c6..0000000000 --- a/tests/expectations/tests/inherit_typedef.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -pub type TypedefedFoo = Foo; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bar)) - ); -} diff --git a/tests/expectations/tests/inline-function.rs b/tests/expectations/tests/inline-function.rs deleted file mode 100644 index 5dcc6c4008..0000000000 --- a/tests/expectations/tests/inline-function.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] diff --git a/tests/expectations/tests/inline_namespace.rs b/tests/expectations/tests/inline_namespace.rs deleted file mode 100644 index 910883de4c..0000000000 --- a/tests/expectations/tests/inline_namespace.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod foo { - #[allow(unused_imports)] - use self::super::super::root; - pub type Ty = ::std::os::raw::c_int; - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar { - pub baz: root::foo::Ty, - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz)) - ); - } -} diff --git a/tests/expectations/tests/inline_namespace_conservative.rs b/tests/expectations/tests/inline_namespace_conservative.rs deleted file mode 100644 index 90fc3793e1..0000000000 --- a/tests/expectations/tests/inline_namespace_conservative.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod foo { - #[allow(unused_imports)] - use self::super::super::root; - pub mod bar { - #[allow(unused_imports)] - use self::super::super::super::root; - pub type Ty = ::std::os::raw::c_int; - } - pub type Ty = ::std::os::raw::c_longlong; - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar { - pub baz: root::foo::bar::Ty, - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(baz)) - ); - } -} diff --git a/tests/expectations/tests/inline_namespace_no_ns_enabled.rs b/tests/expectations/tests/inline_namespace_no_ns_enabled.rs deleted file mode 100644 index e208f0dcc6..0000000000 --- a/tests/expectations/tests/inline_namespace_no_ns_enabled.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug)] -pub struct std_basic_string { - pub hider: std_basic_string_Alloc_hider, - pub length: ::std::os::raw::c_ulong, - pub __bindgen_anon_1: std_basic_string__bindgen_ty_1, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct std_basic_string_Alloc_hider { - pub storage: *mut ::std::os::raw::c_void, -} -impl Default for std_basic_string_Alloc_hider { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug)] -pub struct std_basic_string__bindgen_ty_1 { - pub inline_storage: [CharT; 4usize], - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for std_basic_string__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for std_basic_string { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/inline_namespace_whitelist.rs b/tests/expectations/tests/inline_namespace_whitelist.rs deleted file mode 100644 index 857a7005fa..0000000000 --- a/tests/expectations/tests/inline_namespace_whitelist.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod std { - #[allow(unused_imports)] - use self::super::super::root; - pub type string = *const ::std::os::raw::c_char; - } -} diff --git a/tests/expectations/tests/inner_const.rs b/tests/expectations/tests/inner_const.rs deleted file mode 100644 index ef62414ee6..0000000000 --- a/tests/expectations/tests/inner_const.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub bar: ::std::os::raw::c_int, -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo3BOOE"] - pub static mut Foo_BOO: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo8whateverE"] - pub static mut Foo_whatever: Foo; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/inner_template_self.rs b/tests/expectations/tests/inner_template_self.rs deleted file mode 100644 index 5a975175e8..0000000000 --- a/tests/expectations/tests/inner_template_self.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct LinkedList { - pub next: *mut LinkedList, - pub prev: *mut LinkedList, -} -impl Default for LinkedList { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct InstantiateIt { - pub m_list: LinkedList, -} -#[test] -fn bindgen_test_layout_InstantiateIt() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(InstantiateIt)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(InstantiateIt)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_list as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(InstantiateIt), - "::", - stringify!(m_list) - ) - ); -} -impl Default for InstantiateIt { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_LinkedList_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of template specialization: ", stringify!(LinkedList)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(LinkedList) - ) - ); -} diff --git a/tests/expectations/tests/int128_t.rs b/tests/expectations/tests/int128_t.rs deleted file mode 100644 index 5dcc6c4008..0000000000 --- a/tests/expectations/tests/int128_t.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] diff --git a/tests/expectations/tests/issue-1034.rs b/tests/expectations/tests/issue-1034.rs deleted file mode 100644 index 687c430593..0000000000 --- a/tests/expectations/tests/issue-1034.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct S2 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub __bindgen_padding_0: u8, -} -#[test] -fn bindgen_test_layout_S2() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(S2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(S2)) - ); -} -impl S2 { - #[inline] - pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs b/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs deleted file mode 100644 index a8a520995e..0000000000 --- a/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct S1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, - pub __bindgen_padding_0: u8, -} -#[test] -fn bindgen_test_layout_S1() { - assert_eq!( - ::std::mem::size_of::(), - 3usize, - concat!("Size of: ", stringify!(S1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(S1)) - ); -} -impl S1 { - #[inline] - pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/issue-1113-template-references.rs b/tests/expectations/tests/issue-1113-template-references.rs deleted file mode 100644 index 3430f27dd7..0000000000 --- a/tests/expectations/tests/issue-1113-template-references.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Entry { - pub _base: K, - pub mData: V, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Entry { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct nsBaseHashtable { - pub _address: u8, -} -pub type nsBaseHashtable_EntryType = Entry; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsBaseHashtable_EntryPtr { - pub mEntry: *mut nsBaseHashtable_EntryType, - pub mExistingEntry: bool, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsBaseHashtable_EntryPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-1118-using-forward-decl.rs b/tests/expectations/tests/issue-1118-using-forward-decl.rs deleted file mode 100644 index d72e08b9eb..0000000000 --- a/tests/expectations/tests/issue-1118-using-forward-decl.rs +++ /dev/null @@ -1,119 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type c = nsTArray; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsTArray_base { - pub d: *mut ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_nsTArray_base() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsTArray_base)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsTArray_base)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsTArray_base), - "::", - stringify!(d) - ) - ); -} -impl Default for nsTArray_base { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsTArray { - pub _base: nsTArray_base, -} -impl Default for nsTArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsIContent { - pub foo: nsTArray, -} -#[test] -fn bindgen_test_layout_nsIContent() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsIContent)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsIContent)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsIContent), - "::", - stringify!(foo) - ) - ); -} -impl Default for nsIContent { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z35Gecko_GetAnonymousContentForElementv"] - pub fn Gecko_GetAnonymousContentForElement() -> *mut nsTArray; -} -#[test] -fn __bindgen_test_layout_nsTArray_open0_ptr_nsIContent_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of template specialization: ", stringify!(nsTArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(nsTArray) - ) - ); -} -#[test] -fn __bindgen_test_layout_nsTArray_open0_ptr_nsIContent_close0_instantiation_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of template specialization: ", stringify!(nsTArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(nsTArray) - ) - ); -} diff --git a/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs b/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs deleted file mode 100644 index a3c5f4f602..0000000000 --- a/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct Foo__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug)] -pub struct Foo { - pub vtable_: *const Foo__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs b/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs deleted file mode 100644 index ed53fdf9ed..0000000000 --- a/tests/expectations/tests/issue-1198-alias-rust-const-mod-bitfield-enum.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod MyDupeEnum { - pub type Type = u32; - pub const A: Type = 0; - pub const A_alias: Type = 0; - pub const B: Type = 1; -} -pub mod MyOtherDupeEnum { - pub type Type = u32; - pub const C: Type = 0; - pub const C_alias: Type = 0; - pub const D: Type = 1; -} diff --git a/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs b/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs deleted file mode 100644 index ed53fdf9ed..0000000000 --- a/tests/expectations/tests/issue-1198-alias-rust-const-mod-enum.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub mod MyDupeEnum { - pub type Type = u32; - pub const A: Type = 0; - pub const A_alias: Type = 0; - pub const B: Type = 1; -} -pub mod MyOtherDupeEnum { - pub type Type = u32; - pub const C: Type = 0; - pub const C_alias: Type = 0; - pub const D: Type = 1; -} diff --git a/tests/expectations/tests/issue-1198-alias-rust-enum.rs b/tests/expectations/tests/issue-1198-alias-rust-enum.rs deleted file mode 100644 index b2902c89a3..0000000000 --- a/tests/expectations/tests/issue-1198-alias-rust-enum.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const MyDupeEnum_A_alias: MyDupeEnum = MyDupeEnum::A; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MyDupeEnum { - A = 0, - B = 1, -} -pub const MyOtherDupeEnum_C_alias: MyOtherDupeEnum = MyOtherDupeEnum::C; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MyOtherDupeEnum { - C = 0, - D = 1, -} diff --git a/tests/expectations/tests/issue-1216-variadic-member.rs b/tests/expectations/tests/issue-1216-variadic-member.rs deleted file mode 100644 index 677993c042..0000000000 --- a/tests/expectations/tests/issue-1216-variadic-member.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -extern "C" { - pub fn f(a: ::std::os::raw::c_int, ...); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - pub f: ::std::option::Option< - unsafe extern "C" fn( - p: *mut ::std::os::raw::c_void, - obj: *mut ::std::os::raw::c_void, - a: ::std::os::raw::c_int, - ... - ), - >, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(f)) - ); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-1281.rs b/tests/expectations/tests/issue-1281.rs deleted file mode 100644 index cfc8ca40c1..0000000000 --- a/tests/expectations/tests/issue-1281.rs +++ /dev/null @@ -1,74 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct bar { - pub u: foo, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct foo { - pub foo: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(foo)) - ); -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(u)) - ); -} -pub type bar_t = bar; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct baz { - pub f: foo, -} -#[test] -fn bindgen_test_layout_baz() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).f as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(baz), "::", stringify!(f)) - ); -} diff --git a/tests/expectations/tests/issue-1285.rs b/tests/expectations/tests/issue-1285.rs deleted file mode 100644 index 7b2c0ae9d4..0000000000 --- a/tests/expectations/tests/issue-1285.rs +++ /dev/null @@ -1,75 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -pub union foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-1291.rs b/tests/expectations/tests/issue-1291.rs deleted file mode 100644 index a233054146..0000000000 --- a/tests/expectations/tests/issue-1291.rs +++ /dev/null @@ -1,179 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[repr(align(16))] -#[derive(Debug, Default, Copy, Clone)] -pub struct RTCRay { - pub org: [f32; 3usize], - pub align0: f32, - pub dir: [f32; 3usize], - pub align1: f32, - pub tnear: f32, - pub tfar: f32, - pub time: f32, - pub mask: ::std::os::raw::c_uint, - pub Ng: [f32; 3usize], - pub align2: f32, - pub u: f32, - pub v: f32, - pub geomID: ::std::os::raw::c_uint, - pub primID: ::std::os::raw::c_uint, - pub instID: ::std::os::raw::c_uint, - pub __bindgen_padding_0: [u32; 3usize], - pub __bindgen_align: [u8; 0usize], -} -#[test] -fn bindgen_test_layout_RTCRay() { - assert_eq!( - ::std::mem::size_of::(), - 96usize, - concat!("Size of: ", stringify!(RTCRay)) - ); - assert_eq!( - ::std::mem::align_of::(), - 16usize, - concat!("Alignment of ", stringify!(RTCRay)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).org as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(org) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).align0 as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(align0) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dir as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(dir) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).align1 as *const _ as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(align1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tnear as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(tnear) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tfar as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(tfar) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).time as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(time) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ng as *const _ as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(Ng) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).align2 as *const _ as usize }, - 60usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(align2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 64usize, - concat!("Offset of field: ", stringify!(RTCRay), "::", stringify!(u)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).v as *const _ as usize }, - 68usize, - concat!("Offset of field: ", stringify!(RTCRay), "::", stringify!(v)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).geomID as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(geomID) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).primID as *const _ as usize }, - 76usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(primID) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).instID as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(RTCRay), - "::", - stringify!(instID) - ) - ); -} diff --git a/tests/expectations/tests/issue-358.rs b/tests/expectations/tests/issue-358.rs deleted file mode 100644 index 892148aa7d..0000000000 --- a/tests/expectations/tests/issue-358.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct JS_PersistentRooted { - pub _base: a, -} -impl Default for JS_PersistentRooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct a { - pub b: *mut a, -} -impl Default for a { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-372.rs b/tests/expectations/tests/issue-372.rs deleted file mode 100644 index a146573bb4..0000000000 --- a/tests/expectations/tests/issue-372.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct i { - pub j: *mut root::i, - pub k: *mut root::i, - pub l: bool, - } - #[test] - fn bindgen_test_layout_i() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(i)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(i)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).j as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(i), "::", stringify!(j)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).k as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(i), "::", stringify!(k)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).l as *const _ as usize }, - 16usize, - concat!("Offset of field: ", stringify!(i), "::", stringify!(l)) - ); - } - impl Default for i { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct d { - pub m: root::i, - } - #[test] - fn bindgen_test_layout_d() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(d)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(d)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(d), "::", stringify!(m)) - ); - } - impl Default for d { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum n { - o = 0, - p = 1, - q = 2, - r = 3, - s = 4, - t = 5, - b = 6, - ae = 7, - e = 8, - ag = 9, - ah = 10, - ai = 11, - } - #[repr(C)] - pub struct F { - pub w: [u64; 33usize], - } - #[test] - fn bindgen_test_layout_F() { - assert_eq!( - ::std::mem::size_of::(), - 264usize, - concat!("Size of: ", stringify!(F)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(F)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).w as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(F), "::", stringify!(w)) - ); - } - impl Default for F { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } -} diff --git a/tests/expectations/tests/issue-410.rs b/tests/expectations/tests/issue-410.rs deleted file mode 100644 index e1ce9df549..0000000000 --- a/tests/expectations/tests/issue-410.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod JS { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Value { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Value() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Value)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Value)) - ); - } - extern "C" { - #[link_name = "\u{1}_ZN2JS5Value1aE10JSWhyMagic"] - pub fn Value_a(this: *mut root::JS::Value, arg1: root::JSWhyMagic); - } - impl Value { - #[inline] - pub unsafe fn a(&mut self, arg1: root::JSWhyMagic) { - Value_a(self, arg1) - } - } - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum JSWhyMagic { - __bindgen_cannot_repr_c_on_empty_enum = 0, - } -} diff --git a/tests/expectations/tests/issue-446.rs b/tests/expectations/tests/issue-446.rs deleted file mode 100644 index d5634d53a6..0000000000 --- a/tests/expectations/tests/issue-446.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct List { - pub next: *mut List, -} -impl Default for List { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct PersistentRooted { - pub root_list: List, -} -impl Default for PersistentRooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-447.rs b/tests/expectations/tests/issue-447.rs deleted file mode 100644 index 11a99ad142..0000000000 --- a/tests/expectations/tests/issue-447.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod mozilla { - #[allow(unused_imports)] - use self::super::super::root; - pub mod detail { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct GuardObjectNotifier { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_GuardObjectNotifier() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(GuardObjectNotifier)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(GuardObjectNotifier)) - ); - } - } - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct JSAutoCompartment { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_JSAutoCompartment() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(JSAutoCompartment)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(JSAutoCompartment)) - ); - } - extern "C" { - #[link_name = "\u{1}_ZN17JSAutoCompartmentC1EN7mozilla6detail19GuardObjectNotifierE"] - pub fn JSAutoCompartment_JSAutoCompartment( - this: *mut root::JSAutoCompartment, - arg1: root::mozilla::detail::GuardObjectNotifier, - ); - } - impl JSAutoCompartment { - #[inline] - pub unsafe fn new(arg1: root::mozilla::detail::GuardObjectNotifier) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - JSAutoCompartment_JSAutoCompartment(&mut __bindgen_tmp, arg1); - __bindgen_tmp - } - } -} diff --git a/tests/expectations/tests/issue-493.rs b/tests/expectations/tests/issue-493.rs deleted file mode 100644 index 69003faffa..0000000000 --- a/tests/expectations/tests/issue-493.rs +++ /dev/null @@ -1,144 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string { - pub _address: u8, -} -pub type basic_string_size_type = ::std::os::raw::c_ulonglong; -pub type basic_string_value_type = ::std::os::raw::c_char; -pub type basic_string_pointer = *mut basic_string_value_type; -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___long { - pub __cap_: basic_string_size_type, - pub __size_: basic_string_size_type, - pub __data_: basic_string_pointer, -} -impl Default for basic_string___long { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub const basic_string___min_cap: basic_string__bindgen_ty_1 = - basic_string__bindgen_ty_1::__min_cap; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum basic_string__bindgen_ty_1 { - __min_cap = 0, -} -#[repr(C)] -pub struct basic_string___short { - pub __bindgen_anon_1: basic_string___short__bindgen_ty_1, - pub __data_: *mut basic_string_value_type, -} -#[repr(C)] -pub union basic_string___short__bindgen_ty_1 { - pub __size_: ::std::os::raw::c_uchar, - pub __lx: basic_string_value_type, - _bindgen_union_align: u8, -} -impl Default for basic_string___short__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for basic_string___short { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct basic_string___ulx { - pub __lx: __BindgenUnionField, - pub __lxx: __BindgenUnionField, - pub bindgen_union_field: [u8; 0usize], -} -impl Default for basic_string___ulx { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub const basic_string___n_words: basic_string__bindgen_ty_2 = - basic_string__bindgen_ty_2::__n_words; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum basic_string__bindgen_ty_2 { - __n_words = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___raw { - pub __words: *mut basic_string_size_type, -} -impl Default for basic_string___raw { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct basic_string___rep { - pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1, -} -#[repr(C)] -pub struct basic_string___rep__bindgen_ty_1 { - pub __l: __BindgenUnionField, - pub __s: __BindgenUnionField, - pub __r: __BindgenUnionField, - pub bindgen_union_field: [u8; 0usize], -} -impl Default for basic_string___rep__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for basic_string___rep { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-493_1_0.rs b/tests/expectations/tests/issue-493_1_0.rs deleted file mode 100644 index a65cd3e846..0000000000 --- a/tests/expectations/tests/issue-493_1_0.rs +++ /dev/null @@ -1,144 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string { - pub _address: u8, -} -pub type basic_string_size_type = ::std::os::raw::c_ulonglong; -pub type basic_string_value_type = ::std::os::raw::c_char; -pub type basic_string_pointer = *mut basic_string_value_type; -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___long { - pub __cap_: basic_string_size_type, - pub __size_: basic_string_size_type, - pub __data_: basic_string_pointer, -} -impl Default for basic_string___long { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub const basic_string___min_cap: basic_string__bindgen_ty_1 = - basic_string__bindgen_ty_1::__min_cap; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum basic_string__bindgen_ty_1 { - __min_cap = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___short { - pub __bindgen_anon_1: basic_string___short__bindgen_ty_1, - pub __data_: *mut basic_string_value_type, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___short__bindgen_ty_1 { - pub __size_: __BindgenUnionField<::std::os::raw::c_uchar>, - pub __lx: __BindgenUnionField, - pub bindgen_union_field: u8, -} -impl Default for basic_string___short { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct basic_string___ulx { - pub __lx: __BindgenUnionField, - pub __lxx: __BindgenUnionField, - pub bindgen_union_field: [u8; 0usize], -} -impl Default for basic_string___ulx { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub const basic_string___n_words: basic_string__bindgen_ty_2 = - basic_string__bindgen_ty_2::__n_words; -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum basic_string__bindgen_ty_2 { - __n_words = 0, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct basic_string___raw { - pub __words: *mut basic_string_size_type, -} -impl Default for basic_string___raw { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct basic_string___rep { - pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct basic_string___rep__bindgen_ty_1 { - pub __l: __BindgenUnionField, - pub __s: __BindgenUnionField, - pub __r: __BindgenUnionField, - pub bindgen_union_field: [u8; 0usize], -} -impl Default for basic_string___rep__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for basic_string___rep { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-537.rs b/tests/expectations/tests/issue-537.rs deleted file mode 100644 index 136f9e0c19..0000000000 --- a/tests/expectations/tests/issue-537.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This should not be opaque; we can see the attributes and can pack the -/// struct. -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct AlignedToOne { - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_AlignedToOne() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(AlignedToOne)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(AlignedToOne)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(AlignedToOne), - "::", - stringify!(i) - ) - ); -} -/// This should be opaque because although we can see the attributes, Rust -/// doesn't have `#[repr(packed = "N")]` yet. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct AlignedToTwo { - pub _bindgen_opaque_blob: [u16; 2usize], -} -#[test] -fn bindgen_test_layout_AlignedToTwo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(AlignedToTwo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(AlignedToTwo)) - ); -} -/// This should not be opaque because although `libclang` doesn't give us the -/// `#pragma pack(1)`, we can detect that alignment is 1 and add -/// `#[repr(packed)]` to the struct ourselves. -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct PackedToOne { - pub x: ::std::os::raw::c_int, - pub y: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_PackedToOne() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(PackedToOne)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(PackedToOne)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(PackedToOne), - "::", - stringify!(x) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).y as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(PackedToOne), - "::", - stringify!(y) - ) - ); -} -/// In this case, even if we can detect the weird alignment triggered by -/// `#pragma pack(2)`, we can't do anything about it because Rust doesn't have -/// `#[repr(packed = "N")]`. Therefore, we must make it opaque. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct PackedToTwo { - pub _bindgen_opaque_blob: [u16; 4usize], -} -#[test] -fn bindgen_test_layout_PackedToTwo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(PackedToTwo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(PackedToTwo)) - ); -} diff --git a/tests/expectations/tests/issue-544-stylo-creduce-2.rs b/tests/expectations/tests/issue-544-stylo-creduce-2.rs deleted file mode 100644 index 071111a453..0000000000 --- a/tests/expectations/tests/issue-544-stylo-creduce-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct Foo { - pub member: Foo_SecondAlias, -} -pub type Foo_FirstAlias = [u8; 0usize]; -pub type Foo_SecondAlias = [u8; 0usize]; -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs deleted file mode 100644 index 1119b7e76a..0000000000 --- a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const ENUM_VARIANT_1: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_1; -pub const ENUM_VARIANT_2: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_2; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - ENUM_VARIANT_1 = 0, - ENUM_VARIANT_2 = 1, -} -pub type JS_Alias = u8; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct JS_Base { - pub f: JS_Alias, -} -impl Default for JS_Base { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct JS_AutoIdVector { - pub _base: JS_Base, -} -#[test] -fn bindgen_test_layout_JS_AutoIdVector() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(JS_AutoIdVector)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(JS_AutoIdVector)) - ); -} -impl Default for JS_AutoIdVector { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_JS_Base_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of template specialization: ", stringify!(JS_Base)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(JS_Base) - ) - ); -} diff --git a/tests/expectations/tests/issue-573-layout-test-failures.rs b/tests/expectations/tests/issue-573-layout-test-failures.rs deleted file mode 100644 index cbb08bb2fe..0000000000 --- a/tests/expectations/tests/issue-573-layout-test-failures.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Outer { - pub i: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct AutoIdVector { - pub ar: Outer, -} -#[test] -fn bindgen_test_layout_AutoIdVector() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(AutoIdVector)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(AutoIdVector)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(AutoIdVector), - "::", - stringify!(ar) - ) - ); -} -#[test] -fn __bindgen_test_layout_Outer_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of template specialization: ", stringify!(Outer)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of template specialization: ", stringify!(Outer)) - ); -} diff --git a/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs b/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs deleted file mode 100644 index db573a7ec9..0000000000 --- a/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs +++ /dev/null @@ -1,56 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct a { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct _bindgen_ty_1 { - pub ar: a, -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<_bindgen_ty_1>(), - 1usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<_bindgen_ty_1>(), - 1usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_bindgen_ty_1>())).ar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(ar) - ) - ); -} -extern "C" { - #[link_name = "\u{1}AutoIdVector"] - pub static mut AutoIdVector: _bindgen_ty_1; -} -#[test] -fn __bindgen_test_layout_a_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of template specialization: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of template specialization: ", stringify!(a)) - ); -} diff --git a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs b/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs deleted file mode 100644 index a7d085b0e2..0000000000 --- a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs +++ /dev/null @@ -1,107 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub type RefPtr = T; - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub _address: u8, -} -pub type A_a = b; -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} -#[repr(C)] -pub struct e { - pub d: RefPtr, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for e { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct f { - pub _address: u8, -} -#[repr(C)] -pub struct g { - pub h: f, -} -#[test] -fn bindgen_test_layout_g() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(g)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(g)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).h as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(g), "::", stringify!(h)) - ); -} -impl Default for g { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct b { - pub _base: g, -} -#[test] -fn bindgen_test_layout_b() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(b)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(b)) - ); -} -impl Default for b { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z25Servo_Element_GetSnapshotv"] - pub fn Servo_Element_GetSnapshot() -> A; -} -#[test] -fn __bindgen_test_layout_f_open0_e_open1_int_close1_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of template specialization: ", stringify!(f)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of template specialization: ", stringify!(f)) - ); -} diff --git a/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs b/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs deleted file mode 100644 index 11571a2d6c..0000000000 --- a/tests/expectations/tests/issue-638-stylo-cannot-find-T-in-this-scope.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RefPtr { - pub use_of_t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for RefPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesRefPtrWithAliasedTypeParam { - pub member: RefPtr>, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -pub type UsesRefPtrWithAliasedTypeParam_V = U; -impl Default for UsesRefPtrWithAliasedTypeParam { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-639-typedef-anon-field.rs b/tests/expectations/tests/issue-639-typedef-anon-field.rs deleted file mode 100644 index 3cc21b19f0..0000000000 --- a/tests/expectations/tests/issue-639-typedef-anon-field.rs +++ /dev/null @@ -1,103 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub bar: Foo_Bar, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo_Bar { - pub abc: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Foo_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo_Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo_Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).abc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Foo_Bar), - "::", - stringify!(abc) - ) - ); -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Baz { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Baz_Bar { - pub abc: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Baz_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Baz_Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Baz_Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).abc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Baz_Bar), - "::", - stringify!(abc) - ) - ); -} -#[test] -fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Baz)) - ); -} diff --git a/tests/expectations/tests/issue-643-inner-struct.rs b/tests/expectations/tests/issue-643-inner-struct.rs deleted file mode 100644 index 7f2d4e3551..0000000000 --- a/tests/expectations/tests/issue-643-inner-struct.rs +++ /dev/null @@ -1,130 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -#[repr(C)] -#[derive(Debug)] -pub struct rte_ring { - pub memzone: *mut rte_memzone, - pub prod: rte_ring_prod, - pub cons: rte_ring_cons, - pub ring: __IncompleteArrayField<*mut ::std::os::raw::c_void>, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct rte_ring_prod { - pub watermark: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_rte_ring_prod() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ring_prod)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ring_prod)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).watermark as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ring_prod), - "::", - stringify!(watermark) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct rte_ring_cons { - pub sc_dequeue: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_rte_ring_cons() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_ring_cons)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_ring_cons)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).sc_dequeue as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ring_cons), - "::", - stringify!(sc_dequeue) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_ring() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_ring)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_ring)) - ); -} -impl Default for rte_ring { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct rte_memzone { - pub _address: u8, -} diff --git a/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs b/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs deleted file mode 100644 index 4d65c0aec5..0000000000 --- a/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[derive(Clone, Copy, Debug)] -pub struct RefPtr(T); - -#[repr(C)] -pub struct HasRefPtr { - pub refptr_member: RefPtr>, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -pub type HasRefPtr_TypedefOfT = T; -impl Default for HasRefPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-648-derive-debug-with-padding.rs b/tests/expectations/tests/issue-648-derive-debug-with-padding.rs deleted file mode 100644 index 0b0eb9a2da..0000000000 --- a/tests/expectations/tests/issue-648-derive-debug-with-padding.rs +++ /dev/null @@ -1,94 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// We emit a `[u8; 63usize]` padding field for this struct, which cannot derive -/// Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end -/// up with the reight alignment, we're waiting on `#[repr(align="N")]` to land -/// in rustc). -#[repr(C)] -#[derive(Copy, Clone)] -pub struct NoDebug { - pub c: ::std::os::raw::c_char, - pub __bindgen_padding_0: [u8; 63usize], -} -#[test] -fn bindgen_test_layout_NoDebug() { - assert_eq!( - ::std::mem::size_of::(), - 64usize, - concat!("Size of: ", stringify!(NoDebug)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NoDebug), - "::", - stringify!(c) - ) - ); -} -impl Default for NoDebug { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for NoDebug { - fn eq(&self, other: &NoDebug) -> bool { - self.c == other.c - } -} -/// This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive -/// Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because -/// we determine Debug derive-ability before we compute padding, which happens at -/// codegen. (Again, we expect to get the alignment wrong for similar reasons.) -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ShouldDeriveDebugButDoesNot { - pub c: [::std::os::raw::c_char; 32usize], - pub d: ::std::os::raw::c_char, - pub __bindgen_padding_0: [u8; 31usize], -} -#[test] -fn bindgen_test_layout_ShouldDeriveDebugButDoesNot() { - assert_eq!( - ::std::mem::size_of::(), - 64usize, - concat!("Size of: ", stringify!(ShouldDeriveDebugButDoesNot)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldDeriveDebugButDoesNot), - "::", - stringify!(c) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(ShouldDeriveDebugButDoesNot), - "::", - stringify!(d) - ) - ); -} -impl Default for ShouldDeriveDebugButDoesNot { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for ShouldDeriveDebugButDoesNot { - fn eq(&self, other: &ShouldDeriveDebugButDoesNot) -> bool { - self.c == other.c && self.d == other.d - } -} diff --git a/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs b/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs deleted file mode 100644 index f5ecbd5e2d..0000000000 --- a/tests/expectations/tests/issue-662-cannot-find-T-in-this-scope.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RefPtr { - pub a: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for RefPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsMainThreadPtrHolder { - pub a: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsMainThreadPtrHolder { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsMainThreadPtrHandle { - pub mPtr: RefPtr>, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsMainThreadPtrHandle { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-662-part-2.rs b/tests/expectations/tests/issue-662-part-2.rs deleted file mode 100644 index 9e685b3add..0000000000 --- a/tests/expectations/tests/issue-662-part-2.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[derive(Clone, Copy, Debug)] -pub struct RefPtr(T); - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsMainThreadPtrHolder { - pub a: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsMainThreadPtrHolder { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct nsMainThreadPtrHandle { - pub mPtr: RefPtr>, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsMainThreadPtrHandle { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-674-1.rs b/tests/expectations/tests/issue-674-1.rs deleted file mode 100644 index 0186549434..0000000000 --- a/tests/expectations/tests/issue-674-1.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod mozilla { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Maybe { - pub _address: u8, - } - pub type Maybe_ValueType = T; - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct CapturingContentInfo { - pub a: u8, - } - #[test] - fn bindgen_test_layout_CapturingContentInfo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(CapturingContentInfo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(CapturingContentInfo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(CapturingContentInfo), - "::", - stringify!(a) - ) - ); - } -} diff --git a/tests/expectations/tests/issue-674-2.rs b/tests/expectations/tests/issue-674-2.rs deleted file mode 100644 index 9394708db7..0000000000 --- a/tests/expectations/tests/issue-674-2.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod JS { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Rooted { - pub _address: u8, - } - pub type Rooted_ElementType = T; - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct c { - pub b: u8, - } - #[test] - fn bindgen_test_layout_c() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(c)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(c)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(c), "::", stringify!(b)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct B { - pub a: root::c, - } - #[test] - fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(B)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(B), "::", stringify!(a)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct StaticRefPtr { - pub _address: u8, - } - #[test] - fn __bindgen_test_layout_StaticRefPtr_open0_B_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!( - "Size of template specialization: ", - stringify!(root::StaticRefPtr) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(root::StaticRefPtr) - ) - ); - } -} diff --git a/tests/expectations/tests/issue-674-3.rs b/tests/expectations/tests/issue-674-3.rs deleted file mode 100644 index 413ad9269a..0000000000 --- a/tests/expectations/tests/issue-674-3.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct nsRefPtrHashtable { - pub _address: u8, - } - pub type nsRefPtrHashtable_UserDataType = *mut PtrType; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct a { - pub b: u8, - } - #[test] - fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(b)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct nsCSSValue { - pub c: root::a, - } - #[test] - fn bindgen_test_layout_nsCSSValue() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(nsCSSValue)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(nsCSSValue)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsCSSValue), - "::", - stringify!(c) - ) - ); - } -} diff --git a/tests/expectations/tests/issue-691-template-parameter-virtual.rs b/tests/expectations/tests/issue-691-template-parameter-virtual.rs deleted file mode 100644 index 4878c1fadf..0000000000 --- a/tests/expectations/tests/issue-691-template-parameter-virtual.rs +++ /dev/null @@ -1,72 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct VirtualMethods__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VirtualMethods { - pub vtable_: *const VirtualMethods__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_VirtualMethods() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(VirtualMethods)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(VirtualMethods)) - ); -} -impl Default for VirtualMethods { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Set { - pub bar: ::std::os::raw::c_int, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ServoElementSnapshotTable { - pub _base: Set, -} -#[test] -fn bindgen_test_layout_ServoElementSnapshotTable() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(ServoElementSnapshotTable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ServoElementSnapshotTable)) - ); -} -impl Default for ServoElementSnapshotTable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_Set_open0_VirtualMethods_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of template specialization: ", stringify!(Set)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of template specialization: ", stringify!(Set)) - ); -} diff --git a/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs deleted file mode 100644 index 806b3f161d..0000000000 --- a/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs +++ /dev/null @@ -1,177 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 32usize], u64>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -impl Foo { - #[inline] - pub fn m_bitfield(&self) -> ::std::os::raw::c_ulong { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 64u8) as u64) } - } - #[inline] - pub fn set_m_bitfield(&mut self, val: ::std::os::raw::c_ulong) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 64u8, val as u64) - } - } - #[inline] - pub fn m_bar(&self) -> ::std::os::raw::c_ulong { - unsafe { ::std::mem::transmute(self._bitfield_1.get(64usize, 64u8) as u64) } - } - #[inline] - pub fn set_m_bar(&mut self, val: ::std::os::raw::c_ulong) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(64usize, 64u8, val as u64) - } - } - #[inline] - pub fn foo(&self) -> ::std::os::raw::c_ulong { - unsafe { ::std::mem::transmute(self._bitfield_1.get(128usize, 1u8) as u64) } - } - #[inline] - pub fn set_foo(&mut self, val: ::std::os::raw::c_ulong) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(128usize, 1u8, val as u64) - } - } - #[inline] - pub fn bar(&self) -> ::std::os::raw::c_ulong { - unsafe { ::std::mem::transmute(self._bitfield_1.get(192usize, 64u8) as u64) } - } - #[inline] - pub fn set_bar(&mut self, val: ::std::os::raw::c_ulong) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(192usize, 64u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - m_bitfield: ::std::os::raw::c_ulong, - m_bar: ::std::os::raw::c_ulong, - foo: ::std::os::raw::c_ulong, - bar: ::std::os::raw::c_ulong, - ) -> __BindgenBitfieldUnit<[u8; 32usize], u64> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 32usize], u64> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 64u8, { - let m_bitfield: u64 = unsafe { ::std::mem::transmute(m_bitfield) }; - m_bitfield as u64 - }); - __bindgen_bitfield_unit.set(64usize, 64u8, { - let m_bar: u64 = unsafe { ::std::mem::transmute(m_bar) }; - m_bar as u64 - }); - __bindgen_bitfield_unit.set(128usize, 1u8, { - let foo: u64 = unsafe { ::std::mem::transmute(foo) }; - foo as u64 - }); - __bindgen_bitfield_unit.set(192usize, 64u8, { - let bar: u64 = unsafe { ::std::mem::transmute(bar) }; - bar as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/issue-801-opaque-sloppiness.rs b/tests/expectations/tests/issue-801-opaque-sloppiness.rs deleted file mode 100644 index 76deebbaa5..0000000000 --- a/tests/expectations/tests/issue-801-opaque-sloppiness.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct A { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct B { - pub _bindgen_opaque_blob: u8, -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(B)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN1B1aE"] - pub static mut B_a: A; -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct C { - pub b: B, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(b)) - ); -} diff --git a/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs b/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs deleted file mode 100644 index 0b1c020d82..0000000000 --- a/tests/expectations/tests/issue-807-opaque-types-methods-being-generated.rs +++ /dev/null @@ -1,130 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Pupper { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Pupper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Pupper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Pupper)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Doggo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Doggo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Doggo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Doggo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct SuchWow { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_SuchWow() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(SuchWow)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(SuchWow)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Opaque { - pub _bindgen_opaque_blob: u8, -} -#[test] -fn bindgen_test_layout_Opaque() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Opaque)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Opaque)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN6Opaque17eleven_out_of_tenEv"] - pub fn Opaque_eleven_out_of_ten(this: *mut Opaque) -> SuchWow; -} -extern "C" { - #[link_name = "\u{1}_ZN6OpaqueC1E6Pupper"] - pub fn Opaque_Opaque(this: *mut Opaque, pup: Pupper); -} -impl Opaque { - #[inline] - pub unsafe fn eleven_out_of_ten(&mut self) -> SuchWow { - Opaque_eleven_out_of_ten(self) - } - #[inline] - pub unsafe fn new(pup: Pupper) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - Opaque_Opaque(&mut __bindgen_tmp, pup); - __bindgen_tmp - } -} -extern "C" { - #[link_name = "\u{1}_ZN6Opaque11MAJESTIC_AFE"] - pub static mut Opaque_MAJESTIC_AF: Doggo; -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Whitelisted { - pub some_member: Opaque, -} -#[test] -fn bindgen_test_layout_Whitelisted() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Whitelisted)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Whitelisted)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).some_member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Whitelisted), - "::", - stringify!(some_member) - ) - ); -} diff --git a/tests/expectations/tests/issue-816.rs b/tests/expectations/tests/issue-816.rs deleted file mode 100644 index 555769a2ca..0000000000 --- a/tests/expectations/tests/issue-816.rs +++ /dev/null @@ -1,767 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct capabilities { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u8>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_capabilities() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(capabilities)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(capabilities)) - ); -} -impl capabilities { - #[inline] - pub fn bit_1(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_1(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_2(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_2(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_3(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_3(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_4(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_4(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_5(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_5(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_6(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_6(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(5usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_7(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_7(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_8(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_8(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_9(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_9(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_10(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_10(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(9usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_11(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_11(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(10usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_12(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_12(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(11usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_13(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_13(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(12usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_14(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_14(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(13usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_15(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_15(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(14usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_16(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_16(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(15usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_17(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_17(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_18(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(17usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_18(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(17usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_19(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(18usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_19(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(18usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_20(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_20(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(19usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_21(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_21(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(20usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_22(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_22(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(21usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_23(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(22usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_23(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(22usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_24(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(23usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_24(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(23usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_25(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_25(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_26(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(25usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_26(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(25usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_27(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(26usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_27(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(26usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_28(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(27usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_28(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(27usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_29(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_29(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(28usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_30(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_30(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(29usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_31(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_31(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(30usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_32(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_32(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(31usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_33(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_33(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(32usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_34(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(33usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_34(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(33usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_35(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(34usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_35(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(34usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_36(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(35usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_36(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(35usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_37(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(36usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_37(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(36usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_38(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(37usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_38(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(37usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_39(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(38usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_39(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(38usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_40(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(39usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_40(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(39usize, 1u8, val as u64) - } - } - #[inline] - pub fn bit_41(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 1u8) as u32) } - } - #[inline] - pub fn set_bit_41(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(40usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - bit_1: ::std::os::raw::c_uint, - bit_2: ::std::os::raw::c_uint, - bit_3: ::std::os::raw::c_uint, - bit_4: ::std::os::raw::c_uint, - bit_5: ::std::os::raw::c_uint, - bit_6: ::std::os::raw::c_uint, - bit_7: ::std::os::raw::c_uint, - bit_8: ::std::os::raw::c_uint, - bit_9: ::std::os::raw::c_uint, - bit_10: ::std::os::raw::c_uint, - bit_11: ::std::os::raw::c_uint, - bit_12: ::std::os::raw::c_uint, - bit_13: ::std::os::raw::c_uint, - bit_14: ::std::os::raw::c_uint, - bit_15: ::std::os::raw::c_uint, - bit_16: ::std::os::raw::c_uint, - bit_17: ::std::os::raw::c_uint, - bit_18: ::std::os::raw::c_uint, - bit_19: ::std::os::raw::c_uint, - bit_20: ::std::os::raw::c_uint, - bit_21: ::std::os::raw::c_uint, - bit_22: ::std::os::raw::c_uint, - bit_23: ::std::os::raw::c_uint, - bit_24: ::std::os::raw::c_uint, - bit_25: ::std::os::raw::c_uint, - bit_26: ::std::os::raw::c_uint, - bit_27: ::std::os::raw::c_uint, - bit_28: ::std::os::raw::c_uint, - bit_29: ::std::os::raw::c_uint, - bit_30: ::std::os::raw::c_uint, - bit_31: ::std::os::raw::c_uint, - bit_32: ::std::os::raw::c_uint, - bit_33: ::std::os::raw::c_uint, - bit_34: ::std::os::raw::c_uint, - bit_35: ::std::os::raw::c_uint, - bit_36: ::std::os::raw::c_uint, - bit_37: ::std::os::raw::c_uint, - bit_38: ::std::os::raw::c_uint, - bit_39: ::std::os::raw::c_uint, - bit_40: ::std::os::raw::c_uint, - bit_41: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 16usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let bit_1: u32 = unsafe { ::std::mem::transmute(bit_1) }; - bit_1 as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let bit_2: u32 = unsafe { ::std::mem::transmute(bit_2) }; - bit_2 as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let bit_3: u32 = unsafe { ::std::mem::transmute(bit_3) }; - bit_3 as u64 - }); - __bindgen_bitfield_unit.set(3usize, 1u8, { - let bit_4: u32 = unsafe { ::std::mem::transmute(bit_4) }; - bit_4 as u64 - }); - __bindgen_bitfield_unit.set(4usize, 1u8, { - let bit_5: u32 = unsafe { ::std::mem::transmute(bit_5) }; - bit_5 as u64 - }); - __bindgen_bitfield_unit.set(5usize, 1u8, { - let bit_6: u32 = unsafe { ::std::mem::transmute(bit_6) }; - bit_6 as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let bit_7: u32 = unsafe { ::std::mem::transmute(bit_7) }; - bit_7 as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let bit_8: u32 = unsafe { ::std::mem::transmute(bit_8) }; - bit_8 as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let bit_9: u32 = unsafe { ::std::mem::transmute(bit_9) }; - bit_9 as u64 - }); - __bindgen_bitfield_unit.set(9usize, 1u8, { - let bit_10: u32 = unsafe { ::std::mem::transmute(bit_10) }; - bit_10 as u64 - }); - __bindgen_bitfield_unit.set(10usize, 1u8, { - let bit_11: u32 = unsafe { ::std::mem::transmute(bit_11) }; - bit_11 as u64 - }); - __bindgen_bitfield_unit.set(11usize, 1u8, { - let bit_12: u32 = unsafe { ::std::mem::transmute(bit_12) }; - bit_12 as u64 - }); - __bindgen_bitfield_unit.set(12usize, 1u8, { - let bit_13: u32 = unsafe { ::std::mem::transmute(bit_13) }; - bit_13 as u64 - }); - __bindgen_bitfield_unit.set(13usize, 1u8, { - let bit_14: u32 = unsafe { ::std::mem::transmute(bit_14) }; - bit_14 as u64 - }); - __bindgen_bitfield_unit.set(14usize, 1u8, { - let bit_15: u32 = unsafe { ::std::mem::transmute(bit_15) }; - bit_15 as u64 - }); - __bindgen_bitfield_unit.set(15usize, 1u8, { - let bit_16: u32 = unsafe { ::std::mem::transmute(bit_16) }; - bit_16 as u64 - }); - __bindgen_bitfield_unit.set(16usize, 1u8, { - let bit_17: u32 = unsafe { ::std::mem::transmute(bit_17) }; - bit_17 as u64 - }); - __bindgen_bitfield_unit.set(17usize, 1u8, { - let bit_18: u32 = unsafe { ::std::mem::transmute(bit_18) }; - bit_18 as u64 - }); - __bindgen_bitfield_unit.set(18usize, 1u8, { - let bit_19: u32 = unsafe { ::std::mem::transmute(bit_19) }; - bit_19 as u64 - }); - __bindgen_bitfield_unit.set(19usize, 1u8, { - let bit_20: u32 = unsafe { ::std::mem::transmute(bit_20) }; - bit_20 as u64 - }); - __bindgen_bitfield_unit.set(20usize, 1u8, { - let bit_21: u32 = unsafe { ::std::mem::transmute(bit_21) }; - bit_21 as u64 - }); - __bindgen_bitfield_unit.set(21usize, 1u8, { - let bit_22: u32 = unsafe { ::std::mem::transmute(bit_22) }; - bit_22 as u64 - }); - __bindgen_bitfield_unit.set(22usize, 1u8, { - let bit_23: u32 = unsafe { ::std::mem::transmute(bit_23) }; - bit_23 as u64 - }); - __bindgen_bitfield_unit.set(23usize, 1u8, { - let bit_24: u32 = unsafe { ::std::mem::transmute(bit_24) }; - bit_24 as u64 - }); - __bindgen_bitfield_unit.set(24usize, 1u8, { - let bit_25: u32 = unsafe { ::std::mem::transmute(bit_25) }; - bit_25 as u64 - }); - __bindgen_bitfield_unit.set(25usize, 1u8, { - let bit_26: u32 = unsafe { ::std::mem::transmute(bit_26) }; - bit_26 as u64 - }); - __bindgen_bitfield_unit.set(26usize, 1u8, { - let bit_27: u32 = unsafe { ::std::mem::transmute(bit_27) }; - bit_27 as u64 - }); - __bindgen_bitfield_unit.set(27usize, 1u8, { - let bit_28: u32 = unsafe { ::std::mem::transmute(bit_28) }; - bit_28 as u64 - }); - __bindgen_bitfield_unit.set(28usize, 1u8, { - let bit_29: u32 = unsafe { ::std::mem::transmute(bit_29) }; - bit_29 as u64 - }); - __bindgen_bitfield_unit.set(29usize, 1u8, { - let bit_30: u32 = unsafe { ::std::mem::transmute(bit_30) }; - bit_30 as u64 - }); - __bindgen_bitfield_unit.set(30usize, 1u8, { - let bit_31: u32 = unsafe { ::std::mem::transmute(bit_31) }; - bit_31 as u64 - }); - __bindgen_bitfield_unit.set(31usize, 1u8, { - let bit_32: u32 = unsafe { ::std::mem::transmute(bit_32) }; - bit_32 as u64 - }); - __bindgen_bitfield_unit.set(32usize, 1u8, { - let bit_33: u32 = unsafe { ::std::mem::transmute(bit_33) }; - bit_33 as u64 - }); - __bindgen_bitfield_unit.set(33usize, 1u8, { - let bit_34: u32 = unsafe { ::std::mem::transmute(bit_34) }; - bit_34 as u64 - }); - __bindgen_bitfield_unit.set(34usize, 1u8, { - let bit_35: u32 = unsafe { ::std::mem::transmute(bit_35) }; - bit_35 as u64 - }); - __bindgen_bitfield_unit.set(35usize, 1u8, { - let bit_36: u32 = unsafe { ::std::mem::transmute(bit_36) }; - bit_36 as u64 - }); - __bindgen_bitfield_unit.set(36usize, 1u8, { - let bit_37: u32 = unsafe { ::std::mem::transmute(bit_37) }; - bit_37 as u64 - }); - __bindgen_bitfield_unit.set(37usize, 1u8, { - let bit_38: u32 = unsafe { ::std::mem::transmute(bit_38) }; - bit_38 as u64 - }); - __bindgen_bitfield_unit.set(38usize, 1u8, { - let bit_39: u32 = unsafe { ::std::mem::transmute(bit_39) }; - bit_39 as u64 - }); - __bindgen_bitfield_unit.set(39usize, 1u8, { - let bit_40: u32 = unsafe { ::std::mem::transmute(bit_40) }; - bit_40 as u64 - }); - __bindgen_bitfield_unit.set(40usize, 1u8, { - let bit_41: u32 = unsafe { ::std::mem::transmute(bit_41) }; - bit_41 as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs b/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs deleted file mode 100644 index 23ef513f4a..0000000000 --- a/tests/expectations/tests/issue-820-unused-template-param-in-alias.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type Foo_self_type = u8; diff --git a/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs b/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs deleted file mode 100644 index 36cae7222f..0000000000 --- a/tests/expectations/tests/issue-826-generating-methods-when-asked-not-to.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/issue-833-1.rs b/tests/expectations/tests/issue-833-1.rs deleted file mode 100644 index aa19dd1bd9..0000000000 --- a/tests/expectations/tests/issue-833-1.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct nsTArray { - pub hdr: *const (), -} - -extern "C" { - pub fn func() -> *mut nsTArray; -} diff --git a/tests/expectations/tests/issue-833-2.rs b/tests/expectations/tests/issue-833-2.rs deleted file mode 100644 index c77f59236e..0000000000 --- a/tests/expectations/tests/issue-833-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -// If the output of this changes, please ensure issue-833-1.hpp changes too - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct nsTArray { - pub _address: u8, -} diff --git a/tests/expectations/tests/issue-834.rs b/tests/expectations/tests/issue-834.rs deleted file mode 100644 index a8014fb92e..0000000000 --- a/tests/expectations/tests/issue-834.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct U { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_U() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(U)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(U)) - ); -} diff --git a/tests/expectations/tests/issue-848-replacement-system-include.rs b/tests/expectations/tests/issue-848-replacement-system-include.rs deleted file mode 100644 index 16fab93a10..0000000000 --- a/tests/expectations/tests/issue-848-replacement-system-include.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This is intended to replace another type, but won't if we treat this include -/// as a system include, because clang doesn't parse comments there. -/// -/// See #848. -/// -///
-#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsTArray { - pub m: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsTArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - pub fn func() -> *mut nsTArray<::std::os::raw::c_int>; -} diff --git a/tests/expectations/tests/issue-888-enum-var-decl-jump.rs b/tests/expectations/tests/issue-888-enum-var-decl-jump.rs deleted file mode 100644 index df48ae24a5..0000000000 --- a/tests/expectations/tests/issue-888-enum-var-decl-jump.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod Halide { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Type { - pub _address: u8, - } - extern "C" { - #[link_name = "\u{1}_ZN6Halide4Type1bE"] - pub static mut Type_b: root::a; - } - #[test] - fn bindgen_test_layout_Type() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Type)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Type)) - ); - } - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum a { - __bindgen_cannot_repr_c_on_empty_enum = 0, - } -} diff --git a/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs b/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs deleted file mode 100644 index 8143921d9a..0000000000 --- a/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub struct BlacklistMe(u8); - - -/// Because this type contains a blacklisted type, it should not derive Copy. -#[repr(C)] -pub struct ShouldNotBeCopy { - pub a: BlacklistMe, -} -#[test] -fn bindgen_test_layout_ShouldNotBeCopy() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ShouldNotBeCopy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ShouldNotBeCopy)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ShouldNotBeCopy), - "::", - stringify!(a) - ) - ); -} -impl Default for ShouldNotBeCopy { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/issue-946.rs b/tests/expectations/tests/issue-946.rs deleted file mode 100644 index 14ed38c65d..0000000000 --- a/tests/expectations/tests/issue-946.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct foo {} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(foo)) - ); -} -pub type bar = foo; diff --git a/tests/expectations/tests/issue_311.rs b/tests/expectations/tests/issue_311.rs deleted file mode 100644 index b857537895..0000000000 --- a/tests/expectations/tests/issue_311.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct jsval_layout { - pub __bindgen_anon_1: root::jsval_layout__bindgen_ty_1, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct jsval_layout__bindgen_ty_1 { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_jsval_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(jsval_layout__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(jsval_layout__bindgen_ty_1)) - ); - } - #[test] - fn bindgen_test_layout_jsval_layout() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(jsval_layout)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(jsval_layout)) - ); - } -} diff --git a/tests/expectations/tests/issue_315.rs b/tests/expectations/tests/issue_315.rs deleted file mode 100644 index d6660523b5..0000000000 --- a/tests/expectations/tests/issue_315.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-pub type c
= a; diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs deleted file mode 100644 index 7e047f6aba..0000000000 --- a/tests/expectations/tests/jsval_layout_opaque.rs +++ /dev/null @@ -1,473 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -pub const JSVAL_TAG_SHIFT: u32 = 47; -pub const JSVAL_PAYLOAD_MASK: u64 = 140737488355327; -pub const JSVAL_TAG_MASK: i64 = -140737488355328; -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueType { - JSVAL_TYPE_DOUBLE = 0, - JSVAL_TYPE_INT32 = 1, - JSVAL_TYPE_UNDEFINED = 2, - JSVAL_TYPE_BOOLEAN = 3, - JSVAL_TYPE_MAGIC = 4, - JSVAL_TYPE_STRING = 5, - JSVAL_TYPE_SYMBOL = 6, - JSVAL_TYPE_NULL = 7, - JSVAL_TYPE_OBJECT = 8, - JSVAL_TYPE_UNKNOWN = 32, - JSVAL_TYPE_MISSING = 33, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueTag { - JSVAL_TAG_MAX_DOUBLE = 131056, - JSVAL_TAG_INT32 = 131057, - JSVAL_TAG_UNDEFINED = 131058, - JSVAL_TAG_STRING = 131061, - JSVAL_TAG_SYMBOL = 131062, - JSVAL_TAG_BOOLEAN = 131059, - JSVAL_TAG_MAGIC = 131060, - JSVAL_TAG_NULL = 131063, - JSVAL_TAG_OBJECT = 131064, -} -#[repr(u64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueShiftedTag { - JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663, - JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696, - JSVAL_SHIFTED_TAG_UNDEFINED = 18444773748872577024, - JSVAL_SHIFTED_TAG_STRING = 18445195961337643008, - JSVAL_SHIFTED_TAG_SYMBOL = 18445336698825998336, - JSVAL_SHIFTED_TAG_BOOLEAN = 18444914486360932352, - JSVAL_SHIFTED_TAG_MAGIC = 18445055223849287680, - JSVAL_SHIFTED_TAG_NULL = 18445477436314353664, - JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSWhyMagic { - /// a hole in a native object's elements - JS_ELEMENTS_HOLE = 0, - /// there is not a pending iterator value - JS_NO_ITER_VALUE = 1, - /// exception value thrown when closing a generator - JS_GENERATOR_CLOSING = 2, - /// compiler sentinel value - JS_NO_CONSTANT = 3, - /// used in debug builds to catch tracing errors - JS_THIS_POISON = 4, - /// used in debug builds to catch tracing errors - JS_ARG_POISON = 5, - /// an empty subnode in the AST serializer - JS_SERIALIZE_NO_NODE = 6, - /// lazy arguments value on the stack - JS_LAZY_ARGUMENTS = 7, - /// optimized-away 'arguments' value - JS_OPTIMIZED_ARGUMENTS = 8, - /// magic value passed to natives to indicate construction - JS_IS_CONSTRUCTING = 9, - /// arguments.callee has been overwritten - JS_OVERWRITTEN_CALLEE = 10, - /// value of static block object slot - JS_BLOCK_NEEDS_CLONE = 11, - /// see class js::HashableValue - JS_HASH_KEY_EMPTY = 12, - /// error while running Ion code - JS_ION_ERROR = 13, - /// missing recover instruction result - JS_ION_BAILOUT = 14, - /// optimized out slot - JS_OPTIMIZED_OUT = 15, - /// uninitialized lexical bindings that produce ReferenceError on touch. - JS_UNINITIALIZED_LEXICAL = 16, - /// for local use - JS_GENERIC_MAGIC = 17, - /// for local use - JS_WHY_MAGIC_COUNT = 18, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union jsval_layout { - pub asBits: u64, - pub debugView: jsval_layout__bindgen_ty_1, - pub s: jsval_layout__bindgen_ty_2, - pub asDouble: f64, - pub asPtr: *mut ::std::os::raw::c_void, - pub asWord: usize, - pub asUIntPtr: usize, - _bindgen_union_align: u64, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct jsval_layout__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(jsval_layout__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(jsval_layout__bindgen_ty_1)) - ); -} -impl Default for jsval_layout__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl jsval_layout__bindgen_ty_1 { - #[inline] - pub fn payload47(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 47u8) as u64) } - } - #[inline] - pub fn set_payload47(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 47u8, val as u64) - } - } - #[inline] - pub fn tag(&self) -> JSValueTag { - unsafe { ::std::mem::transmute(self._bitfield_1.get(47usize, 17u8) as u32) } - } - #[inline] - pub fn set_tag(&mut self, val: JSValueTag) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(47usize, 17u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - payload47: u64, - tag: JSValueTag, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u64> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u64> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 47u8, { - let payload47: u64 = unsafe { ::std::mem::transmute(payload47) }; - payload47 as u64 - }); - __bindgen_bitfield_unit.set(47usize, 17u8, { - let tag: u32 = unsafe { ::std::mem::transmute(tag) }; - tag as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct jsval_layout__bindgen_ty_2 { - pub payload: jsval_layout__bindgen_ty_2__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union jsval_layout__bindgen_ty_2__bindgen_ty_1 { - pub i32: i32, - pub u32: u32, - pub why: JSWhyMagic, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).i32 as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(i32) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).u32 as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(u32) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).why as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(why) - ) - ); -} -impl Default for jsval_layout__bindgen_ty_2__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(jsval_layout__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(jsval_layout__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).payload as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2), - "::", - stringify!(payload) - ) - ); -} -impl Default for jsval_layout__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_jsval_layout() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(jsval_layout)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(jsval_layout)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asBits as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asBits) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).debugView as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(debugView) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(s) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asDouble as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asDouble) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asPtr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asPtr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asWord as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asWord) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asUIntPtr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asUIntPtr) - ) - ); -} -impl Default for jsval_layout { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Value { - pub data: jsval_layout, -} -#[test] -fn bindgen_test_layout_Value() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Value)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Value)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Value), - "::", - stringify!(data) - ) - ); -} -impl Default for Value { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/jsval_layout_opaque_1_0.rs b/tests/expectations/tests/jsval_layout_opaque_1_0.rs deleted file mode 100644 index 29ce27ad5b..0000000000 --- a/tests/expectations/tests/jsval_layout_opaque_1_0.rs +++ /dev/null @@ -1,521 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -pub const JSVAL_TAG_SHIFT: u32 = 47; -pub const JSVAL_PAYLOAD_MASK: u64 = 140737488355327; -pub const JSVAL_TAG_MASK: i64 = -140737488355328; -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueType { - JSVAL_TYPE_DOUBLE = 0, - JSVAL_TYPE_INT32 = 1, - JSVAL_TYPE_UNDEFINED = 2, - JSVAL_TYPE_BOOLEAN = 3, - JSVAL_TYPE_MAGIC = 4, - JSVAL_TYPE_STRING = 5, - JSVAL_TYPE_SYMBOL = 6, - JSVAL_TYPE_NULL = 7, - JSVAL_TYPE_OBJECT = 8, - JSVAL_TYPE_UNKNOWN = 32, - JSVAL_TYPE_MISSING = 33, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueTag { - JSVAL_TAG_MAX_DOUBLE = 131056, - JSVAL_TAG_INT32 = 131057, - JSVAL_TAG_UNDEFINED = 131058, - JSVAL_TAG_STRING = 131061, - JSVAL_TAG_SYMBOL = 131062, - JSVAL_TAG_BOOLEAN = 131059, - JSVAL_TAG_MAGIC = 131060, - JSVAL_TAG_NULL = 131063, - JSVAL_TAG_OBJECT = 131064, -} -#[repr(u64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueShiftedTag { - JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663, - JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696, - JSVAL_SHIFTED_TAG_UNDEFINED = 18444773748872577024, - JSVAL_SHIFTED_TAG_STRING = 18445195961337643008, - JSVAL_SHIFTED_TAG_SYMBOL = 18445336698825998336, - JSVAL_SHIFTED_TAG_BOOLEAN = 18444914486360932352, - JSVAL_SHIFTED_TAG_MAGIC = 18445055223849287680, - JSVAL_SHIFTED_TAG_NULL = 18445477436314353664, - JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSWhyMagic { - /// a hole in a native object's elements - JS_ELEMENTS_HOLE = 0, - /// there is not a pending iterator value - JS_NO_ITER_VALUE = 1, - /// exception value thrown when closing a generator - JS_GENERATOR_CLOSING = 2, - /// compiler sentinel value - JS_NO_CONSTANT = 3, - /// used in debug builds to catch tracing errors - JS_THIS_POISON = 4, - /// used in debug builds to catch tracing errors - JS_ARG_POISON = 5, - /// an empty subnode in the AST serializer - JS_SERIALIZE_NO_NODE = 6, - /// lazy arguments value on the stack - JS_LAZY_ARGUMENTS = 7, - /// optimized-away 'arguments' value - JS_OPTIMIZED_ARGUMENTS = 8, - /// magic value passed to natives to indicate construction - JS_IS_CONSTRUCTING = 9, - /// arguments.callee has been overwritten - JS_OVERWRITTEN_CALLEE = 10, - /// value of static block object slot - JS_BLOCK_NEEDS_CLONE = 11, - /// see class js::HashableValue - JS_HASH_KEY_EMPTY = 12, - /// error while running Ion code - JS_ION_ERROR = 13, - /// missing recover instruction result - JS_ION_BAILOUT = 14, - /// optimized out slot - JS_OPTIMIZED_OUT = 15, - /// uninitialized lexical bindings that produce ReferenceError on touch. - JS_UNINITIALIZED_LEXICAL = 16, - /// for local use - JS_GENERIC_MAGIC = 17, - /// for local use - JS_WHY_MAGIC_COUNT = 18, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct jsval_layout { - pub asBits: __BindgenUnionField, - pub debugView: __BindgenUnionField, - pub s: __BindgenUnionField, - pub asDouble: __BindgenUnionField, - pub asPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub asWord: __BindgenUnionField, - pub asUIntPtr: __BindgenUnionField, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct jsval_layout__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(jsval_layout__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(jsval_layout__bindgen_ty_1)) - ); -} -impl Clone for jsval_layout__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -impl Default for jsval_layout__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl jsval_layout__bindgen_ty_1 { - #[inline] - pub fn payload47(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 47u8) as u64) } - } - #[inline] - pub fn set_payload47(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 47u8, val as u64) - } - } - #[inline] - pub fn tag(&self) -> JSValueTag { - unsafe { ::std::mem::transmute(self._bitfield_1.get(47usize, 17u8) as u32) } - } - #[inline] - pub fn set_tag(&mut self, val: JSValueTag) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(47usize, 17u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - payload47: u64, - tag: JSValueTag, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u64> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u64> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 47u8, { - let payload47: u64 = unsafe { ::std::mem::transmute(payload47) }; - payload47 as u64 - }); - __bindgen_bitfield_unit.set(47usize, 17u8, { - let tag: u32 = unsafe { ::std::mem::transmute(tag) }; - tag as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct jsval_layout__bindgen_ty_2 { - pub payload: jsval_layout__bindgen_ty_2__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct jsval_layout__bindgen_ty_2__bindgen_ty_1 { - pub i32: __BindgenUnionField, - pub u32: __BindgenUnionField, - pub why: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).i32 as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(i32) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).u32 as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(u32) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).why as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(why) - ) - ); -} -impl Clone for jsval_layout__bindgen_ty_2__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(jsval_layout__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(jsval_layout__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).payload as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout__bindgen_ty_2), - "::", - stringify!(payload) - ) - ); -} -impl Clone for jsval_layout__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_jsval_layout() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(jsval_layout)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(jsval_layout)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asBits as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asBits) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).debugView as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(debugView) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(s) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asDouble as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asDouble) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asPtr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asPtr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asWord as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asWord) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).asUIntPtr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(jsval_layout), - "::", - stringify!(asUIntPtr) - ) - ); -} -impl Clone for jsval_layout { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct Value { - pub data: jsval_layout, -} -#[test] -fn bindgen_test_layout_Value() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Value)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Value)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Value), - "::", - stringify!(data) - ) - ); -} -impl Clone for Value { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/keywords.rs b/tests/expectations/tests/keywords.rs deleted file mode 100644 index b354f431f9..0000000000 --- a/tests/expectations/tests/keywords.rs +++ /dev/null @@ -1,202 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}u8"] - pub static mut u8: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}u16"] - pub static mut u16: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}u32"] - pub static mut u32: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}u64"] - pub static mut u64: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}i8"] - pub static mut i8: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}i16"] - pub static mut i16: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}i32"] - pub static mut i32: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}i64"] - pub static mut i64: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}f32"] - pub static mut f32: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}f64"] - pub static mut f64: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}usize"] - pub static mut usize: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}isize"] - pub static mut isize: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}as"] - pub static mut as_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}box"] - pub static mut box_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}crate"] - pub static mut crate_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}false"] - pub static mut false_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}fn"] - pub static mut fn_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}impl"] - pub static mut impl_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}in"] - pub static mut in_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}let"] - pub static mut let_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}loop"] - pub static mut loop_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}match"] - pub static mut match_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}mod"] - pub static mut mod_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}move"] - pub static mut move_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}mut"] - pub static mut mut_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}pub"] - pub static mut pub_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}ref"] - pub static mut ref_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}self"] - pub static mut self_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}Self"] - pub static mut Self_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}super"] - pub static mut super_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}trait"] - pub static mut trait_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}true"] - pub static mut true_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}type"] - pub static mut type_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}unsafe"] - pub static mut unsafe_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}use"] - pub static mut use_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}where"] - pub static mut where_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}abstract"] - pub static mut abstract_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}alignof"] - pub static mut alignof_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}become"] - pub static mut become_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}final"] - pub static mut final_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}macro"] - pub static mut macro_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}offsetof"] - pub static mut offsetof_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}override"] - pub static mut override_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}priv"] - pub static mut priv_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}proc"] - pub static mut proc_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}pure"] - pub static mut pure_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}unsized"] - pub static mut unsized_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}virtual"] - pub static mut virtual_: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}yield"] - pub static mut yield_: ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/layout.rs b/tests/expectations/tests/layout.rs deleted file mode 100644 index 2790446c1a..0000000000 --- a/tests/expectations/tests/layout.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct header { - pub _bindgen_opaque_blob: [u8; 16usize], -} -#[test] -fn bindgen_test_layout_header() { - assert_eq!( - ::std::mem::size_of::
(), - 16usize, - concat!("Size of: ", stringify!(header)) - ); -} -impl Default for header { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/layout_align.rs b/tests/expectations/tests/layout_align.rs deleted file mode 100644 index a0f7f8ad3b..0000000000 --- a/tests/expectations/tests/layout_align.rs +++ /dev/null @@ -1,244 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -#[repr(C)] -#[derive(Debug)] -pub struct rte_kni_fifo { - /// < Next position to be written - pub write: ::std::os::raw::c_uint, - /// < Next position to be read - pub read: ::std::os::raw::c_uint, - /// < Circular buffer length - pub len: ::std::os::raw::c_uint, - /// < Pointer size - for 32/64 bit OS - pub elem_size: ::std::os::raw::c_uint, - /// < The buffer contains mbuf pointers - pub buffer: __IncompleteArrayField<*mut ::std::os::raw::c_void>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_rte_kni_fifo() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_kni_fifo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_kni_fifo)) - ); -} -impl Default for rte_kni_fifo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct rte_eth_link { - /// < ETH_SPEED_NUM_ - pub link_speed: u32, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub __bindgen_padding_0: [u8; 3usize], - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_rte_eth_link() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_eth_link)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_link)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).link_speed as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_link), - "::", - stringify!(link_speed) - ) - ); -} -impl rte_eth_link { - #[inline] - pub fn link_duplex(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } - } - #[inline] - pub fn set_link_duplex(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn link_autoneg(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } - } - #[inline] - pub fn set_link_autoneg(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn link_status(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } - } - #[inline] - pub fn set_link_status(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - link_duplex: u16, - link_autoneg: u16, - link_status: u16, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let link_duplex: u16 = unsafe { ::std::mem::transmute(link_duplex) }; - link_duplex as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let link_autoneg: u16 = unsafe { ::std::mem::transmute(link_autoneg) }; - link_autoneg as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let link_status: u16 = unsafe { ::std::mem::transmute(link_status) }; - link_status as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/layout_arp.rs b/tests/expectations/tests/layout_arp.rs deleted file mode 100644 index 7516f5e40e..0000000000 --- a/tests/expectations/tests/layout_arp.rs +++ /dev/null @@ -1,200 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const ETHER_ADDR_LEN: u32 = 6; -pub const ARP_HRD_ETHER: u32 = 1; -pub const ARP_OP_REQUEST: u32 = 1; -pub const ARP_OP_REPLY: u32 = 2; -pub const ARP_OP_REVREQUEST: u32 = 3; -pub const ARP_OP_REVREPLY: u32 = 4; -pub const ARP_OP_INVREQUEST: u32 = 8; -pub const ARP_OP_INVREPLY: u32 = 9; -/// Ethernet address: -/// A universally administered address is uniquely assigned to a device by its -/// manufacturer. The first three octets (in transmission order) contain the -/// Organizationally Unique Identifier (OUI). The following three (MAC-48 and -/// EUI-48) octets are assigned by that organization with the only constraint -/// of uniqueness. -/// A locally administered address is assigned to a device by a network -/// administrator and does not contain OUIs. -/// See http://standards.ieee.org/regauth/groupmac/tutorial.html -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct ether_addr { - /// < Addr bytes in tx order - pub addr_bytes: [u8; 6usize], -} -#[test] -fn bindgen_test_layout_ether_addr() { - assert_eq!( - ::std::mem::size_of::(), - 6usize, - concat!("Size of: ", stringify!(ether_addr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ether_addr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).addr_bytes as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ether_addr), - "::", - stringify!(addr_bytes) - ) - ); -} -/// ARP header IPv4 payload. -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct arp_ipv4 { - /// < sender hardware address - pub arp_sha: ether_addr, - /// < sender IP address - pub arp_sip: u32, - /// < target hardware address - pub arp_tha: ether_addr, - /// < target IP address - pub arp_tip: u32, -} -#[test] -fn bindgen_test_layout_arp_ipv4() { - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(arp_ipv4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(arp_ipv4)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_sha as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(arp_ipv4), - "::", - stringify!(arp_sha) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_sip as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(arp_ipv4), - "::", - stringify!(arp_sip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_tha as *const _ as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(arp_ipv4), - "::", - stringify!(arp_tha) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_tip as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(arp_ipv4), - "::", - stringify!(arp_tip) - ) - ); -} -/// ARP header. -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct arp_hdr { - pub arp_hrd: u16, - pub arp_pro: u16, - pub arp_hln: u8, - pub arp_pln: u8, - pub arp_op: u16, - pub arp_data: arp_ipv4, -} -#[test] -fn bindgen_test_layout_arp_hdr() { - assert_eq!( - ::std::mem::size_of::(), - 28usize, - concat!("Size of: ", stringify!(arp_hdr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(arp_hdr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_hrd as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_hrd) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_pro as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_pro) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_hln as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_hln) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_pln as *const _ as usize }, - 5usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_pln) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_op as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_op) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arp_data as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(arp_hdr), - "::", - stringify!(arp_data) - ) - ); -} diff --git a/tests/expectations/tests/layout_array.rs b/tests/expectations/tests/layout_array.rs deleted file mode 100644 index 7ca267dcbd..0000000000 --- a/tests/expectations/tests/layout_array.rs +++ /dev/null @@ -1,341 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -pub const RTE_MEMPOOL_OPS_NAMESIZE: u32 = 32; -pub const RTE_MEMPOOL_MAX_OPS_IDX: u32 = 16; -pub const RTE_HEAP_NUM_FREELISTS: u32 = 13; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct rte_mempool { - _unused: [u8; 0], -} -/// Prototype for implementation specific data provisioning function. -/// -/// The function should provide the implementation specific memory for -/// for use by the other mempool ops functions in a given mempool ops struct. -/// E.g. the default ops provides an instance of the rte_ring for this purpose. -/// it will most likely point to a different type of data structure, and -/// will be transparent to the application programmer. -/// This function should set mp->pool_data. -pub type rte_mempool_alloc_t = - ::std::option::Option ::std::os::raw::c_int>; -/// Free the opaque private data pointed to by mp->pool_data pointer. -pub type rte_mempool_free_t = ::std::option::Option; -/// Enqueue an object into the external pool. -pub type rte_mempool_enqueue_t = ::std::option::Option< - unsafe extern "C" fn( - mp: *mut rte_mempool, - obj_table: *const *const ::std::os::raw::c_void, - n: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int, ->; -/// Dequeue an object from the external pool. -pub type rte_mempool_dequeue_t = ::std::option::Option< - unsafe extern "C" fn( - mp: *mut rte_mempool, - obj_table: *mut *mut ::std::os::raw::c_void, - n: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int, ->; -/// Return the number of available objects in the external pool. -pub type rte_mempool_get_count = - ::std::option::Option ::std::os::raw::c_uint>; -/// Structure defining mempool operations structure -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_mempool_ops { - /// < Name of mempool ops struct. - pub name: [::std::os::raw::c_char; 32usize], - /// < Allocate private data. - pub alloc: rte_mempool_alloc_t, - /// < Free the external pool. - pub free: rte_mempool_free_t, - /// < Enqueue an object. - pub enqueue: rte_mempool_enqueue_t, - /// < Dequeue an object. - pub dequeue: rte_mempool_dequeue_t, - /// < Get qty of available objs. - pub get_count: rte_mempool_get_count, - pub __bindgen_padding_0: [u64; 7usize], -} -#[test] -fn bindgen_test_layout_rte_mempool_ops() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(rte_mempool_ops)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(name) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).alloc as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(alloc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).free as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(free) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).enqueue as *const _ as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(enqueue) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dequeue as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(dequeue) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).get_count as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops), - "::", - stringify!(get_count) - ) - ); -} -impl Default for rte_mempool_ops { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for rte_mempool_ops { - fn eq(&self, other: &rte_mempool_ops) -> bool { - self.name == other.name && self.alloc == other.alloc && self.free == other.free - && self.enqueue == other.enqueue && self.dequeue == other.dequeue - && self.get_count == other.get_count - } -} -/// The rte_spinlock_t type. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_spinlock_t { - /// < lock status 0 = unlocked, 1 = locked - pub locked: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_rte_spinlock_t() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_spinlock_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_spinlock_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).locked as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_spinlock_t), - "::", - stringify!(locked) - ) - ); -} -/// Structure storing the table of registered ops structs, each of which contain -/// the function pointers for the mempool ops functions. -/// Each process has its own storage for this ops struct array so that -/// the mempools can be shared across primary and secondary processes. -/// The indices used to access the array are valid across processes, whereas -/// any function pointers stored directly in the mempool struct would not be. -/// This results in us simply having "ops_index" in the mempool struct. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_mempool_ops_table { - /// < Spinlock for add/delete. - pub sl: rte_spinlock_t, - /// < Number of used ops structs in the table. - pub num_ops: u32, - pub __bindgen_padding_0: [u64; 7usize], - /// Storage for all possible ops structs. - pub ops: [rte_mempool_ops; 16usize], -} -#[test] -fn bindgen_test_layout_rte_mempool_ops_table() { - assert_eq!( - ::std::mem::size_of::(), - 2112usize, - concat!("Size of: ", stringify!(rte_mempool_ops_table)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).sl as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops_table), - "::", - stringify!(sl) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).num_ops as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops_table), - "::", - stringify!(num_ops) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ops as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_mempool_ops_table), - "::", - stringify!(ops) - ) - ); -} -impl Default for rte_mempool_ops_table { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// Structure to hold malloc heap -#[repr(C)] -#[derive(Copy, Clone)] -pub struct malloc_heap { - pub lock: rte_spinlock_t, - pub free_head: [malloc_heap__bindgen_ty_1; 13usize], - pub alloc_count: ::std::os::raw::c_uint, - pub total_size: usize, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct malloc_heap__bindgen_ty_1 { - pub lh_first: *mut malloc_elem, -} -#[test] -fn bindgen_test_layout_malloc_heap__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(malloc_heap__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(malloc_heap__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lh_first as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(malloc_heap__bindgen_ty_1), - "::", - stringify!(lh_first) - ) - ); -} -impl Default for malloc_heap__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_malloc_heap() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(malloc_heap)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lock as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(malloc_heap), - "::", - stringify!(lock) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).free_head as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(malloc_heap), - "::", - stringify!(free_head) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).alloc_count as *const _ as usize }, - 112usize, - concat!( - "Offset of field: ", - stringify!(malloc_heap), - "::", - stringify!(alloc_count) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).total_size as *const _ as usize }, - 120usize, - concat!( - "Offset of field: ", - stringify!(malloc_heap), - "::", - stringify!(total_size) - ) - ); -} -impl Default for malloc_heap { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for malloc_heap { - fn eq(&self, other: &malloc_heap) -> bool { - self.lock == other.lock && self.free_head == other.free_head - && self.alloc_count == other.alloc_count && self.total_size == other.total_size - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct malloc_elem { - pub _address: u8, -} diff --git a/tests/expectations/tests/layout_array_too_long.rs b/tests/expectations/tests/layout_array_too_long.rs deleted file mode 100644 index 24ab41a478..0000000000 --- a/tests/expectations/tests/layout_array_too_long.rs +++ /dev/null @@ -1,299 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -pub const RTE_LIBRTE_IP_FRAG_MAX_FRAG: u32 = 4; -pub const IP_LAST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_LAST_FRAG_IDX; -pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX; -pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM; -pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - /// < index of last fragment - IP_LAST_FRAG_IDX = 0, - /// < index of first fragment - IP_FIRST_FRAG_IDX = 1, - /// < minimum number of fragments - IP_MIN_FRAG_NUM = 2, - IP_MAX_FRAG_NUM = 4, -} -/// @internal fragmented mbuf -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ip_frag { - /// < offset into the packet - pub ofs: u16, - /// < length of fragment - pub len: u16, - /// < fragment mbuf - pub mb: *mut rte_mbuf, -} -#[test] -fn bindgen_test_layout_ip_frag() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ip_frag)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ofs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(ofs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).len as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mb as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(mb) - ) - ); -} -impl Default for ip_frag { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// @internal to uniquely indetify fragmented datagram. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ip_frag_key { - /// < src address, first 8 bytes used for IPv4 - pub src_dst: [u64; 4usize], - /// < dst address - pub id: u32, - /// < src/dst key length - pub key_len: u32, -} -#[test] -fn bindgen_test_layout_ip_frag_key() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(ip_frag_key)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag_key)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_dst as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(src_dst) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(id) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).key_len as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(key_len) - ) - ); -} -/// @internal Fragmented packet to reassemble. -/// First two entries in the frags[] array are for the last and first fragments. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ip_frag_pkt { - /// < LRU list - pub lru: ip_frag_pkt__bindgen_ty_1, - /// < fragmentation key - pub key: ip_frag_key, - /// < creation timestamp - pub start: u64, - /// < expected reassembled size - pub total_size: u32, - /// < size of fragments received - pub frag_size: u32, - /// < index of next entry to fill - pub last_idx: u32, - /// < fragments - pub frags: [ip_frag; 4usize], - pub __bindgen_padding_0: [u64; 6usize], -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ip_frag_pkt__bindgen_ty_1 { - pub tqe_next: *mut ip_frag_pkt, - pub tqe_prev: *mut *mut ip_frag_pkt, -} -#[test] -fn bindgen_test_layout_ip_frag_pkt__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ip_frag_pkt__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag_pkt__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tqe_next as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt__bindgen_ty_1), - "::", - stringify!(tqe_next) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tqe_prev as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt__bindgen_ty_1), - "::", - stringify!(tqe_prev) - ) - ); -} -impl Default for ip_frag_pkt__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_ip_frag_pkt() { - assert_eq!( - ::std::mem::size_of::(), - 192usize, - concat!("Size of: ", stringify!(ip_frag_pkt)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lru as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(lru) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).key as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(key) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).start as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(start) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).total_size as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(total_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).frag_size as *const _ as usize }, - 68usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(frag_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).last_idx as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(last_idx) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).frags as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(frags) - ) - ); -} -impl Default for ip_frag_pkt { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for ip_frag_pkt { - fn eq(&self, other: &ip_frag_pkt) -> bool { - self.lru == other.lru && self.key == other.key && self.start == other.start - && self.total_size == other.total_size && self.frag_size == other.frag_size - && self.last_idx == other.last_idx && self.frags == other.frags - } -} -/// < fragment mbuf -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mbuf { - pub _address: u8, -} diff --git a/tests/expectations/tests/layout_cmdline_token.rs b/tests/expectations/tests/layout_cmdline_token.rs deleted file mode 100644 index d583e641dc..0000000000 --- a/tests/expectations/tests/layout_cmdline_token.rs +++ /dev/null @@ -1,254 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -/// Stores a pointer to the ops struct, and the offset: the place to -/// write the parsed result in the destination structure. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct cmdline_token_hdr { - pub ops: *mut cmdline_token_ops, - pub offset: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_cmdline_token_hdr() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(cmdline_token_hdr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(cmdline_token_hdr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ops as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_hdr), - "::", - stringify!(ops) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).offset as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_hdr), - "::", - stringify!(offset) - ) - ); -} -impl Default for cmdline_token_hdr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type cmdline_parse_token_hdr_t = cmdline_token_hdr; -/// A token is defined by this structure. -/// -/// parse() takes the token as first argument, then the source buffer -/// starting at the token we want to parse. The 3rd arg is a pointer -/// where we store the parsed data (as binary). It returns the number of -/// parsed chars on success and a negative value on error. -/// -/// complete_get_nb() returns the number of possible values for this -/// token if completion is possible. If it is NULL or if it returns 0, -/// no completion is possible. -/// -/// complete_get_elt() copy in dstbuf (the size is specified in the -/// parameter) the i-th possible completion for this token. returns 0 -/// on success or and a negative value on error. -/// -/// get_help() fills the dstbuf with the help for the token. It returns -/// -1 on error and 0 on success. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct cmdline_token_ops { - /// parse(token ptr, buf, res pts, buf len) - pub parse: ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut cmdline_parse_token_hdr_t, - arg2: *const ::std::os::raw::c_char, - arg3: *mut ::std::os::raw::c_void, - arg4: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int, - >, - /// return the num of possible choices for this token - pub complete_get_nb: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut cmdline_parse_token_hdr_t) -> ::std::os::raw::c_int, - >, - /// return the elt x for this token (token, idx, dstbuf, size) - pub complete_get_elt: ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut cmdline_parse_token_hdr_t, - arg2: ::std::os::raw::c_int, - arg3: *mut ::std::os::raw::c_char, - arg4: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int, - >, - /// get help for this token (token, dstbuf, size) - pub get_help: ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut cmdline_parse_token_hdr_t, - arg2: *mut ::std::os::raw::c_char, - arg3: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int, - >, -} -#[test] -fn bindgen_test_layout_cmdline_token_ops() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(cmdline_token_ops)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(cmdline_token_ops)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).parse as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_ops), - "::", - stringify!(parse) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).complete_get_nb as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_ops), - "::", - stringify!(complete_get_nb) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).complete_get_elt as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_ops), - "::", - stringify!(complete_get_elt) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).get_help as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_ops), - "::", - stringify!(get_help) - ) - ); -} -impl Default for cmdline_token_ops { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum cmdline_numtype { - UINT8 = 0, - UINT16 = 1, - UINT32 = 2, - UINT64 = 3, - INT8 = 4, - INT16 = 5, - INT32 = 6, - INT64 = 7, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct cmdline_token_num_data { - pub type_: cmdline_numtype, -} -#[test] -fn bindgen_test_layout_cmdline_token_num_data() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(cmdline_token_num_data)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(cmdline_token_num_data)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_num_data), - "::", - stringify!(type_) - ) - ); -} -impl Default for cmdline_token_num_data { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct cmdline_token_num { - pub hdr: cmdline_token_hdr, - pub num_data: cmdline_token_num_data, -} -#[test] -fn bindgen_test_layout_cmdline_token_num() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(cmdline_token_num)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(cmdline_token_num)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).hdr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_num), - "::", - stringify!(hdr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).num_data as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(cmdline_token_num), - "::", - stringify!(num_data) - ) - ); -} -impl Default for cmdline_token_num { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type cmdline_parse_token_num_t = cmdline_token_num; diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs deleted file mode 100644 index 71d03ef64a..0000000000 --- a/tests/expectations/tests/layout_eth_conf.rs +++ /dev/null @@ -1,1994 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -pub const ETH_MQ_RX_RSS_FLAG: u32 = 1; -pub const ETH_MQ_RX_DCB_FLAG: u32 = 2; -pub const ETH_MQ_RX_VMDQ_FLAG: u32 = 4; -pub const ETH_VMDQ_MAX_VLAN_FILTERS: u32 = 64; -pub const ETH_DCB_NUM_USER_PRIORITIES: u32 = 8; -pub const ETH_VMDQ_DCB_NUM_QUEUES: u32 = 128; -pub const ETH_DCB_NUM_QUEUES: u32 = 128; -pub const RTE_ETH_FDIR_MAX_FLEXLEN: u32 = 16; -pub const RTE_ETH_INSET_SIZE_MAX: u32 = 128; -pub const RTE_ETH_FLOW_UNKNOWN: u32 = 0; -pub const RTE_ETH_FLOW_RAW: u32 = 1; -pub const RTE_ETH_FLOW_IPV4: u32 = 2; -pub const RTE_ETH_FLOW_FRAG_IPV4: u32 = 3; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_TCP: u32 = 4; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_UDP: u32 = 5; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: u32 = 6; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: u32 = 7; -pub const RTE_ETH_FLOW_IPV6: u32 = 8; -pub const RTE_ETH_FLOW_FRAG_IPV6: u32 = 9; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_TCP: u32 = 10; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_UDP: u32 = 11; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: u32 = 12; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: u32 = 13; -pub const RTE_ETH_FLOW_L2_PAYLOAD: u32 = 14; -pub const RTE_ETH_FLOW_IPV6_EX: u32 = 15; -pub const RTE_ETH_FLOW_IPV6_TCP_EX: u32 = 16; -pub const RTE_ETH_FLOW_IPV6_UDP_EX: u32 = 17; -pub const RTE_ETH_FLOW_PORT: u32 = 18; -pub const RTE_ETH_FLOW_VXLAN: u32 = 19; -pub const RTE_ETH_FLOW_GENEVE: u32 = 20; -pub const RTE_ETH_FLOW_NVGRE: u32 = 21; -pub const RTE_ETH_FLOW_MAX: u32 = 22; -#[repr(u32)] -/// A set of values to identify what method is to be used to route -/// packets to multiple queues. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_rx_mq_mode { - /// None of DCB,RSS or VMDQ mode - ETH_MQ_RX_NONE = 0, - /// For RX side, only RSS is on - ETH_MQ_RX_RSS = 1, - /// For RX side,only DCB is on. - ETH_MQ_RX_DCB = 2, - /// Both DCB and RSS enable - ETH_MQ_RX_DCB_RSS = 3, - /// Only VMDQ, no RSS nor DCB - ETH_MQ_RX_VMDQ_ONLY = 4, - /// RSS mode with VMDQ - ETH_MQ_RX_VMDQ_RSS = 5, - /// Use VMDQ+DCB to route traffic to queues - ETH_MQ_RX_VMDQ_DCB = 6, - /// Enable both VMDQ and DCB in VMDq - ETH_MQ_RX_VMDQ_DCB_RSS = 7, -} -/// A structure used to configure the RX features of an Ethernet port. -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_rxmode { - /// The multi-queue packet distribution mode to be used, e.g. RSS. - pub mq_mode: rte_eth_rx_mq_mode, - /// < Only used if jumbo_frame enabled. - pub max_rx_pkt_len: u32, - /// < hdr buf size (header_split enabled). - pub split_hdr_size: u16, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, -} -#[test] -fn bindgen_test_layout_rte_eth_rxmode() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_rxmode)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_rxmode)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mq_mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(mq_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).max_rx_pkt_len as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(max_rx_pkt_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).split_hdr_size as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(split_hdr_size) - ) - ); -} -impl Default for rte_eth_rxmode { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl rte_eth_rxmode { - #[inline] - pub fn header_split(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } - } - #[inline] - pub fn set_header_split(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_ip_checksum(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_ip_checksum(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_filter(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_filter(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_strip(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_strip(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_extend(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_extend(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 1u8, val as u64) - } - } - #[inline] - pub fn jumbo_frame(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } - } - #[inline] - pub fn set_jumbo_frame(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(5usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_strip_crc(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_strip_crc(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn enable_scatter(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) } - } - #[inline] - pub fn set_enable_scatter(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn enable_lro(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } - } - #[inline] - pub fn set_enable_lro(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - header_split: u16, - hw_ip_checksum: u16, - hw_vlan_filter: u16, - hw_vlan_strip: u16, - hw_vlan_extend: u16, - jumbo_frame: u16, - hw_strip_crc: u16, - enable_scatter: u16, - enable_lro: u16, - ) -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let header_split: u16 = unsafe { ::std::mem::transmute(header_split) }; - header_split as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let hw_ip_checksum: u16 = unsafe { ::std::mem::transmute(hw_ip_checksum) }; - hw_ip_checksum as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let hw_vlan_filter: u16 = unsafe { ::std::mem::transmute(hw_vlan_filter) }; - hw_vlan_filter as u64 - }); - __bindgen_bitfield_unit.set(3usize, 1u8, { - let hw_vlan_strip: u16 = unsafe { ::std::mem::transmute(hw_vlan_strip) }; - hw_vlan_strip as u64 - }); - __bindgen_bitfield_unit.set(4usize, 1u8, { - let hw_vlan_extend: u16 = unsafe { ::std::mem::transmute(hw_vlan_extend) }; - hw_vlan_extend as u64 - }); - __bindgen_bitfield_unit.set(5usize, 1u8, { - let jumbo_frame: u16 = unsafe { ::std::mem::transmute(jumbo_frame) }; - jumbo_frame as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let hw_strip_crc: u16 = unsafe { ::std::mem::transmute(hw_strip_crc) }; - hw_strip_crc as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let enable_scatter: u16 = unsafe { ::std::mem::transmute(enable_scatter) }; - enable_scatter as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let enable_lro: u16 = unsafe { ::std::mem::transmute(enable_lro) }; - enable_lro as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(u32)] -/// A set of values to identify what method is to be used to transmit -/// packets using multi-TCs. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_tx_mq_mode { - /// < It is in neither DCB nor VT mode. - ETH_MQ_TX_NONE = 0, - /// < For TX side,only DCB is on. - ETH_MQ_TX_DCB = 1, - /// < For TX side,both DCB and VT is on. - ETH_MQ_TX_VMDQ_DCB = 2, - /// < Only VT on, no DCB - ETH_MQ_TX_VMDQ_ONLY = 3, -} -/// A structure used to configure the TX features of an Ethernet port. -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_txmode { - /// < TX multi-queues mode. - pub mq_mode: rte_eth_tx_mq_mode, - pub pvid: u16, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub __bindgen_padding_0: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_txmode() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_eth_txmode)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_txmode)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mq_mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_txmode), - "::", - stringify!(mq_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pvid as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_txmode), - "::", - stringify!(pvid) - ) - ); -} -impl Default for rte_eth_txmode { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl rte_eth_txmode { - #[inline] - pub fn hw_vlan_reject_tagged(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_reject_tagged(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_reject_untagged(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_reject_untagged(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_insert_pvid(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_insert_pvid(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - hw_vlan_reject_tagged: u8, - hw_vlan_reject_untagged: u8, - hw_vlan_insert_pvid: u8, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let hw_vlan_reject_tagged: u8 = unsafe { ::std::mem::transmute(hw_vlan_reject_tagged) }; - hw_vlan_reject_tagged as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let hw_vlan_reject_untagged: u8 = - unsafe { ::std::mem::transmute(hw_vlan_reject_untagged) }; - hw_vlan_reject_untagged as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let hw_vlan_insert_pvid: u8 = unsafe { ::std::mem::transmute(hw_vlan_insert_pvid) }; - hw_vlan_insert_pvid as u64 - }); - __bindgen_bitfield_unit - } -} -/// A structure used to configure the Receive Side Scaling (RSS) feature -/// of an Ethernet port. -/// If not NULL, the *rss_key* pointer of the *rss_conf* structure points -/// to an array holding the RSS key to use for hashing specific header -/// fields of received packets. The length of this array should be indicated -/// by *rss_key_len* below. Otherwise, a default random hash key is used by -/// the device driver. -/// -/// The *rss_key_len* field of the *rss_conf* structure indicates the length -/// in bytes of the array pointed by *rss_key*. To be compatible, this length -/// will be checked in i40e only. Others assume 40 bytes to be used as before. -/// -/// The *rss_hf* field of the *rss_conf* structure indicates the different -/// types of IPv4/IPv6 packets to which the RSS hashing must be applied. -/// Supplying an *rss_hf* equal to zero disables the RSS feature. -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_rss_conf { - /// < If not NULL, 40-byte hash key. - pub rss_key: *mut u8, - /// < hash key length in bytes. - pub rss_key_len: u8, - /// < Hash functions to apply - see below. - pub rss_hf: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_rss_conf() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(rte_eth_rss_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_rss_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_key as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_key) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_key_len as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_key_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_hf as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_hf) - ) - ); -} -impl Default for rte_eth_rss_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(u32)] -/// This enum indicates the possible number of traffic classes -/// in DCB configratioins -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_nb_tcs { - /// < 4 TCs with DCB. - ETH_4_TCS = 4, - /// < 8 TCs with DCB. - ETH_8_TCS = 8, -} -#[repr(u32)] -/// This enum indicates the possible number of queue pools -/// in VMDQ configurations. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_nb_pools { - /// < 8 VMDq pools. - ETH_8_POOLS = 8, - /// < 16 VMDq pools. - ETH_16_POOLS = 16, - /// < 32 VMDq pools. - ETH_32_POOLS = 32, - /// < 64 VMDq pools. - ETH_64_POOLS = 64, -} -/// A structure used to configure the VMDQ+DCB feature -/// of an Ethernet port. -/// -/// Using this feature, packets are routed to a pool of queues, based -/// on the vlan id in the vlan tag, and then to a specific queue within -/// that pool, using the user priority vlan tag field. -/// -/// A default pool may be used, if desired, to route all traffic which -/// does not match the vlan filter rules. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_eth_vmdq_dcb_conf { - /// < With DCB, 16 or 32 pools - pub nb_queue_pools: rte_eth_nb_pools, - /// < If non-zero, use a default pool - pub enable_default_pool: u8, - /// < The default pool, if applicable - pub default_pool: u8, - /// < We can have up to 64 filters/mappings - pub nb_pool_maps: u8, - /// < VMDq vlan pool maps. - pub pool_map: [rte_eth_vmdq_dcb_conf__bindgen_ty_1; 64usize], - pub dcb_tc: [u8; 8usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_dcb_conf__bindgen_ty_1 { - /// < The vlan id of the received frame - pub vlan_id: u16, - /// < Bitmask of pools for packet rx - pub pools: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_id as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1), - "::", - stringify!(vlan_id) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).pools as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1), - "::", - stringify!(pools) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_conf() { - assert_eq!( - ::std::mem::size_of::(), - 1040usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_dcb_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_default_pool as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(enable_default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).default_pool as *const _ as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_pool_maps as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(nb_pool_maps) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool_map as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(pool_map) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 1032usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Default for rte_eth_vmdq_dcb_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_dcb_rx_conf { - /// < Possible DCB TCs, 4 or 8 TCs - pub nb_tcs: rte_eth_nb_tcs, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_dcb_rx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_dcb_rx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_dcb_rx_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_tcs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_rx_conf), - "::", - stringify!(nb_tcs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_rx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Default for rte_eth_dcb_rx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_dcb_tx_conf { - /// < With DCB, 16 or 32 pools. - pub nb_queue_pools: rte_eth_nb_pools, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_dcb_tx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_tx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_tx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Default for rte_eth_vmdq_dcb_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_dcb_tx_conf { - /// < Possible DCB TCs, 4 or 8 TCs. - pub nb_tcs: rte_eth_nb_tcs, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_dcb_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_dcb_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_dcb_tx_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_tcs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_tx_conf), - "::", - stringify!(nb_tcs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_tx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Default for rte_eth_dcb_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_tx_conf { - /// < VMDq mode, 64 pools. - pub nb_queue_pools: rte_eth_nb_pools, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_tx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_tx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); -} -impl Default for rte_eth_vmdq_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_eth_vmdq_rx_conf { - /// < VMDq only mode, 8 or 64 pools - pub nb_queue_pools: rte_eth_nb_pools, - /// < If non-zero, use a default pool - pub enable_default_pool: u8, - /// < The default pool, if applicable - pub default_pool: u8, - /// < Enable VT loop back - pub enable_loop_back: u8, - /// < We can have up to 64 filters/mappings - pub nb_pool_maps: u8, - /// < Flags from ETH_VMDQ_ACCEPT_* - pub rx_mode: u32, - /// < VMDq vlan pool maps. - pub pool_map: [rte_eth_vmdq_rx_conf__bindgen_ty_1; 64usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_rx_conf__bindgen_ty_1 { - /// < The vlan id of the received frame - pub vlan_id: u16, - /// < Bitmask of pools for packet rx - pub pools: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_rx_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_id as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1), - "::", - stringify!(vlan_id) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).pools as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1), - "::", - stringify!(pools) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_rx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 1040usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_rx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_rx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_default_pool as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(enable_default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).default_pool as *const _ as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_loop_back as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(enable_loop_back) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_pool_maps as *const _ as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(nb_pool_maps) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_mode as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(rx_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool_map as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(pool_map) - ) - ); -} -impl Default for rte_eth_vmdq_rx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(u32)] -/// Flow Director setting modes: none, signature or perfect. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_mode { - /// < Disable FDIR support. - RTE_FDIR_MODE_NONE = 0, - /// < Enable FDIR signature filter mode. - RTE_FDIR_MODE_SIGNATURE = 1, - /// < Enable FDIR perfect filter mode. - RTE_FDIR_MODE_PERFECT = 2, - /// < Enable FDIR filter mode - MAC VLAN. - RTE_FDIR_MODE_PERFECT_MAC_VLAN = 3, - /// < Enable FDIR filter mode - tunnel. - RTE_FDIR_MODE_PERFECT_TUNNEL = 4, -} -#[repr(u32)] -/// Memory space that can be configured to store Flow Director filters -/// in the board memory. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_pballoc_type { - /// < 64k. - RTE_FDIR_PBALLOC_64K = 0, - /// < 128k. - RTE_FDIR_PBALLOC_128K = 1, - /// < 256k. - RTE_FDIR_PBALLOC_256K = 2, -} -#[repr(u32)] -/// Select report mode of FDIR hash information in RX descriptors. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_status_mode { - /// < Never report FDIR hash. - RTE_FDIR_NO_REPORT_STATUS = 0, - /// < Only report FDIR hash for matching pkts. - RTE_FDIR_REPORT_STATUS = 1, - /// < Always report FDIR hash. - RTE_FDIR_REPORT_STATUS_ALWAYS = 2, -} -/// A structure used to define the input for IPV4 flow -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_ipv4_flow { - /// < IPv4 source address in big endian. - pub src_ip: u32, - /// < IPv4 destination address in big endian. - pub dst_ip: u32, - /// < Type of service to match. - pub tos: u8, - /// < Time to live to match. - pub ttl: u8, - /// < Protocol, next header in big endian. - pub proto: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_ipv4_flow() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_ipv4_flow)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_ipv4_flow)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_ip as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(src_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_ip as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(dst_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tos as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(tos) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ttl as *const _ as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(ttl) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).proto as *const _ as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(proto) - ) - ); -} -/// A structure used to define the input for IPV6 flow -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_ipv6_flow { - /// < IPv6 source address in big endian. - pub src_ip: [u32; 4usize], - /// < IPv6 destination address in big endian. - pub dst_ip: [u32; 4usize], - /// < Traffic class to match. - pub tc: u8, - /// < Protocol, next header to match. - pub proto: u8, - /// < Hop limits to match. - pub hop_limits: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_ipv6_flow() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_eth_ipv6_flow)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_ipv6_flow)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_ip as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(src_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_ip as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(dst_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tc as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(tc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).proto as *const _ as usize }, - 33usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(proto) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).hop_limits as *const _ as usize }, - 34usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(hop_limits) - ) - ); -} -/// A structure used to configure FDIR masks that are used by the device -/// to match the various fields of RX packet headers. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_masks { - /// < Bit mask for vlan_tci in big endian - pub vlan_tci_mask: u16, - /// Bit mask for ipv4 flow in big endian. - pub ipv4_mask: rte_eth_ipv4_flow, - /// Bit maks for ipv6 flow in big endian. - pub ipv6_mask: rte_eth_ipv6_flow, - /// Bit mask for L4 source port in big endian. - pub src_port_mask: u16, - /// Bit mask for L4 destination port in big endian. - pub dst_port_mask: u16, - /// 6 bit mask for proper 6 bytes of Mac address, bit 0 matches the - /// first byte on the wire - pub mac_addr_byte_mask: u8, - /// Bit mask for tunnel ID in big endian. - pub tunnel_id_mask: u32, - /// < 1 - Match tunnel type, - /// 0 - Ignore tunnel type. - pub tunnel_type_mask: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_masks() { - assert_eq!( - ::std::mem::size_of::(), - 68usize, - concat!("Size of: ", stringify!(rte_eth_fdir_masks)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_masks)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_tci_mask as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(vlan_tci_mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ipv4_mask as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(ipv4_mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ipv6_mask as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(ipv6_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).src_port_mask as *const _ as usize - }, - 52usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(src_port_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dst_port_mask as *const _ as usize - }, - 54usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(dst_port_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mac_addr_byte_mask as *const _ as usize - }, - 56usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(mac_addr_byte_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tunnel_id_mask as *const _ as usize - }, - 60usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(tunnel_id_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tunnel_type_mask as *const _ as usize - }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(tunnel_type_mask) - ) - ); -} -#[repr(u32)] -/// Payload type -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_payload_type { - RTE_ETH_PAYLOAD_UNKNOWN = 0, - RTE_ETH_RAW_PAYLOAD = 1, - RTE_ETH_L2_PAYLOAD = 2, - RTE_ETH_L3_PAYLOAD = 3, - RTE_ETH_L4_PAYLOAD = 4, - RTE_ETH_PAYLOAD_MAX = 8, -} -/// A structure used to select bytes extracted from the protocol layers to -/// flexible payload for filter -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_flex_payload_cfg { - /// < Payload type - pub type_: rte_eth_payload_type, - pub src_offset: [u16; 16usize], -} -#[test] -fn bindgen_test_layout_rte_eth_flex_payload_cfg() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_eth_flex_payload_cfg)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_flex_payload_cfg)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_flex_payload_cfg), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).src_offset as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_flex_payload_cfg), - "::", - stringify!(src_offset) - ) - ); -} -impl Default for rte_eth_flex_payload_cfg { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to define FDIR masks for flexible payload -/// for each flow type -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_flex_mask { - pub flow_type: u16, - pub mask: [u8; 16usize], -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_flex_mask() { - assert_eq!( - ::std::mem::size_of::(), - 18usize, - concat!("Size of: ", stringify!(rte_eth_fdir_flex_mask)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_flex_mask)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).flow_type as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_mask), - "::", - stringify!(flow_type) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_mask), - "::", - stringify!(mask) - ) - ); -} -/// A structure used to define all flexible payload related setting -/// include flex payload and flex mask -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_flex_conf { - /// < The number of following payload cfg - pub nb_payloads: u16, - /// < The number of following mask - pub nb_flexmasks: u16, - pub flex_set: [rte_eth_flex_payload_cfg; 8usize], - pub flex_mask: [rte_eth_fdir_flex_mask; 22usize], -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_flex_conf() { - assert_eq!( - ::std::mem::size_of::(), - 688usize, - concat!("Size of: ", stringify!(rte_eth_fdir_flex_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_flex_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_payloads as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(nb_payloads) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_flexmasks as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(nb_flexmasks) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).flex_set as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(flex_set) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).flex_mask as *const _ as usize - }, - 292usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(flex_mask) - ) - ); -} -impl Default for rte_eth_fdir_flex_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to configure the Flow Director (FDIR) feature -/// of an Ethernet port. -/// -/// If mode is RTE_FDIR_DISABLE, the pballoc value is ignored. -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_fdir_conf { - /// < Flow Director mode. - pub mode: rte_fdir_mode, - /// < Space for FDIR filters. - pub pballoc: rte_fdir_pballoc_type, - /// < How to report FDIR hash. - pub status: rte_fdir_status_mode, - /// RX queue of packets matching a "drop" filter in perfect mode. - pub drop_queue: u8, - pub mask: rte_eth_fdir_masks, - pub flex_conf: rte_eth_fdir_flex_conf, -} -#[test] -fn bindgen_test_layout_rte_fdir_conf() { - assert_eq!( - ::std::mem::size_of::(), - 772usize, - concat!("Size of: ", stringify!(rte_fdir_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_fdir_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pballoc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(pballoc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).status as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(status) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).drop_queue as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(drop_queue) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).flex_conf as *const _ as usize }, - 84usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(flex_conf) - ) - ); -} -impl Default for rte_fdir_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to enable/disable specific device interrupts. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_intr_conf { - /// enable/disable lsc interrupt. 0 (default) - disable, 1 enable - pub lsc: u16, - /// enable/disable rxq interrupt. 0 (default) - disable, 1 enable - pub rxq: u16, -} -#[test] -fn bindgen_test_layout_rte_intr_conf() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_intr_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_intr_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lsc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_intr_conf), - "::", - stringify!(lsc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rxq as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_intr_conf), - "::", - stringify!(rxq) - ) - ); -} -/// A structure used to configure an Ethernet port. -/// Depending upon the RX multi-queue mode, extra advanced -/// configuration settings may be needed. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_eth_conf { - /// < bitmap of ETH_LINK_SPEED_XXX of speeds to be - /// used. ETH_LINK_SPEED_FIXED disables link - /// autonegotiation, and a unique speed shall be - /// set. Otherwise, the bitmap defines the set of - /// speeds to be advertised. If the special value - /// ETH_LINK_SPEED_AUTONEG (0) is used, all speeds - /// supported are advertised. - pub link_speeds: u32, - /// < Port RX configuration. - pub rxmode: rte_eth_rxmode, - /// < Port TX configuration. - pub txmode: rte_eth_txmode, - /// < Loopback operation mode. By default the value - /// is 0, meaning the loopback mode is disabled. - /// Read the datasheet of given ethernet controller - /// for details. The possible values of this field - /// are defined in implementation of each driver. - pub lpbk_mode: u32, - /// < Port RX filtering configuration (union). - pub rx_adv_conf: rte_eth_conf__bindgen_ty_1, - /// < Port TX DCB configuration (union). - pub tx_adv_conf: rte_eth_conf__bindgen_ty_2, - /// Currently,Priority Flow Control(PFC) are supported,if DCB with PFC - /// is needed,and the variable must be set ETH_DCB_PFC_SUPPORT. - pub dcb_capability_en: u32, - /// < FDIR configuration. - pub fdir_conf: rte_fdir_conf, - /// < Interrupt mode configuration. - pub intr_conf: rte_intr_conf, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_eth_conf__bindgen_ty_1 { - /// < Port RSS configuration - pub rss_conf: rte_eth_rss_conf, - pub vmdq_dcb_conf: rte_eth_vmdq_dcb_conf, - pub dcb_rx_conf: rte_eth_dcb_rx_conf, - pub vmdq_rx_conf: rte_eth_vmdq_rx_conf, -} -#[test] -fn bindgen_test_layout_rte_eth_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2120usize, - concat!("Size of: ", stringify!(rte_eth_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_conf__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).rss_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(rss_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_dcb_conf as *const _ - as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(vmdq_dcb_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dcb_rx_conf as *const _ as usize - }, - 1064usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(dcb_rx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_rx_conf as *const _ as usize - }, - 1080usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(vmdq_rx_conf) - ) - ); -} -impl Default for rte_eth_conf__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_eth_conf__bindgen_ty_2 { - pub vmdq_dcb_tx_conf: rte_eth_vmdq_dcb_tx_conf, - pub dcb_tx_conf: rte_eth_dcb_tx_conf, - pub vmdq_tx_conf: rte_eth_vmdq_tx_conf, - _bindgen_union_align: [u32; 3usize], -} -#[test] -fn bindgen_test_layout_rte_eth_conf__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_conf__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_conf__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_dcb_tx_conf as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(vmdq_dcb_tx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dcb_tx_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(dcb_tx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_tx_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(vmdq_tx_conf) - ) - ); -} -impl Default for rte_eth_conf__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_eth_conf() { - assert_eq!( - ::std::mem::size_of::(), - 2944usize, - concat!("Size of: ", stringify!(rte_eth_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).link_speeds as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(link_speeds) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rxmode as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(rxmode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).txmode as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(txmode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lpbk_mode as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(lpbk_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_adv_conf as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(rx_adv_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tx_adv_conf as *const _ as usize }, - 2152usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(tx_adv_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_capability_en as *const _ as usize }, - 2164usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(dcb_capability_en) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fdir_conf as *const _ as usize }, - 2168usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(fdir_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).intr_conf as *const _ as usize }, - 2940usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(intr_conf) - ) - ); -} -impl Default for rte_eth_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/layout_eth_conf_1_0.rs b/tests/expectations/tests/layout_eth_conf_1_0.rs deleted file mode 100644 index e9a09f54ea..0000000000 --- a/tests/expectations/tests/layout_eth_conf_1_0.rs +++ /dev/null @@ -1,2142 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -pub const ETH_MQ_RX_RSS_FLAG: u32 = 1; -pub const ETH_MQ_RX_DCB_FLAG: u32 = 2; -pub const ETH_MQ_RX_VMDQ_FLAG: u32 = 4; -pub const ETH_VMDQ_MAX_VLAN_FILTERS: u32 = 64; -pub const ETH_DCB_NUM_USER_PRIORITIES: u32 = 8; -pub const ETH_VMDQ_DCB_NUM_QUEUES: u32 = 128; -pub const ETH_DCB_NUM_QUEUES: u32 = 128; -pub const RTE_ETH_FDIR_MAX_FLEXLEN: u32 = 16; -pub const RTE_ETH_INSET_SIZE_MAX: u32 = 128; -pub const RTE_ETH_FLOW_UNKNOWN: u32 = 0; -pub const RTE_ETH_FLOW_RAW: u32 = 1; -pub const RTE_ETH_FLOW_IPV4: u32 = 2; -pub const RTE_ETH_FLOW_FRAG_IPV4: u32 = 3; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_TCP: u32 = 4; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_UDP: u32 = 5; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: u32 = 6; -pub const RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: u32 = 7; -pub const RTE_ETH_FLOW_IPV6: u32 = 8; -pub const RTE_ETH_FLOW_FRAG_IPV6: u32 = 9; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_TCP: u32 = 10; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_UDP: u32 = 11; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: u32 = 12; -pub const RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: u32 = 13; -pub const RTE_ETH_FLOW_L2_PAYLOAD: u32 = 14; -pub const RTE_ETH_FLOW_IPV6_EX: u32 = 15; -pub const RTE_ETH_FLOW_IPV6_TCP_EX: u32 = 16; -pub const RTE_ETH_FLOW_IPV6_UDP_EX: u32 = 17; -pub const RTE_ETH_FLOW_PORT: u32 = 18; -pub const RTE_ETH_FLOW_VXLAN: u32 = 19; -pub const RTE_ETH_FLOW_GENEVE: u32 = 20; -pub const RTE_ETH_FLOW_NVGRE: u32 = 21; -pub const RTE_ETH_FLOW_MAX: u32 = 22; -#[repr(u32)] -/// A set of values to identify what method is to be used to route -/// packets to multiple queues. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_rx_mq_mode { - /// None of DCB,RSS or VMDQ mode - ETH_MQ_RX_NONE = 0, - /// For RX side, only RSS is on - ETH_MQ_RX_RSS = 1, - /// For RX side,only DCB is on. - ETH_MQ_RX_DCB = 2, - /// Both DCB and RSS enable - ETH_MQ_RX_DCB_RSS = 3, - /// Only VMDQ, no RSS nor DCB - ETH_MQ_RX_VMDQ_ONLY = 4, - /// RSS mode with VMDQ - ETH_MQ_RX_VMDQ_RSS = 5, - /// Use VMDQ+DCB to route traffic to queues - ETH_MQ_RX_VMDQ_DCB = 6, - /// Enable both VMDQ and DCB in VMDq - ETH_MQ_RX_VMDQ_DCB_RSS = 7, -} -/// A structure used to configure the RX features of an Ethernet port. -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_rxmode { - /// The multi-queue packet distribution mode to be used, e.g. RSS. - pub mq_mode: rte_eth_rx_mq_mode, - /// < Only used if jumbo_frame enabled. - pub max_rx_pkt_len: u32, - /// < hdr buf size (header_split enabled). - pub split_hdr_size: u16, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, -} -#[test] -fn bindgen_test_layout_rte_eth_rxmode() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_rxmode)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_rxmode)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mq_mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(mq_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).max_rx_pkt_len as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(max_rx_pkt_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).split_hdr_size as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rxmode), - "::", - stringify!(split_hdr_size) - ) - ); -} -impl Clone for rte_eth_rxmode { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_rxmode { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl rte_eth_rxmode { - #[inline] - pub fn header_split(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } - } - #[inline] - pub fn set_header_split(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_ip_checksum(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_ip_checksum(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_filter(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_filter(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_strip(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_strip(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(3usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_extend(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_vlan_extend(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 1u8, val as u64) - } - } - #[inline] - pub fn jumbo_frame(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } - } - #[inline] - pub fn set_jumbo_frame(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(5usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_strip_crc(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) } - } - #[inline] - pub fn set_hw_strip_crc(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn enable_scatter(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) } - } - #[inline] - pub fn set_enable_scatter(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn enable_lro(&self) -> u16 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } - } - #[inline] - pub fn set_enable_lro(&mut self, val: u16) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - header_split: u16, - hw_ip_checksum: u16, - hw_vlan_filter: u16, - hw_vlan_strip: u16, - hw_vlan_extend: u16, - jumbo_frame: u16, - hw_strip_crc: u16, - enable_scatter: u16, - enable_lro: u16, - ) -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let header_split: u16 = unsafe { ::std::mem::transmute(header_split) }; - header_split as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let hw_ip_checksum: u16 = unsafe { ::std::mem::transmute(hw_ip_checksum) }; - hw_ip_checksum as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let hw_vlan_filter: u16 = unsafe { ::std::mem::transmute(hw_vlan_filter) }; - hw_vlan_filter as u64 - }); - __bindgen_bitfield_unit.set(3usize, 1u8, { - let hw_vlan_strip: u16 = unsafe { ::std::mem::transmute(hw_vlan_strip) }; - hw_vlan_strip as u64 - }); - __bindgen_bitfield_unit.set(4usize, 1u8, { - let hw_vlan_extend: u16 = unsafe { ::std::mem::transmute(hw_vlan_extend) }; - hw_vlan_extend as u64 - }); - __bindgen_bitfield_unit.set(5usize, 1u8, { - let jumbo_frame: u16 = unsafe { ::std::mem::transmute(jumbo_frame) }; - jumbo_frame as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let hw_strip_crc: u16 = unsafe { ::std::mem::transmute(hw_strip_crc) }; - hw_strip_crc as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let enable_scatter: u16 = unsafe { ::std::mem::transmute(enable_scatter) }; - enable_scatter as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let enable_lro: u16 = unsafe { ::std::mem::transmute(enable_lro) }; - enable_lro as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(u32)] -/// A set of values to identify what method is to be used to transmit -/// packets using multi-TCs. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_tx_mq_mode { - /// < It is in neither DCB nor VT mode. - ETH_MQ_TX_NONE = 0, - /// < For TX side,only DCB is on. - ETH_MQ_TX_DCB = 1, - /// < For TX side,both DCB and VT is on. - ETH_MQ_TX_VMDQ_DCB = 2, - /// < Only VT on, no DCB - ETH_MQ_TX_VMDQ_ONLY = 3, -} -/// A structure used to configure the TX features of an Ethernet port. -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_txmode { - /// < TX multi-queues mode. - pub mq_mode: rte_eth_tx_mq_mode, - pub pvid: u16, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub __bindgen_padding_0: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_txmode() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_eth_txmode)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_txmode)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mq_mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_txmode), - "::", - stringify!(mq_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pvid as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_txmode), - "::", - stringify!(pvid) - ) - ); -} -impl Clone for rte_eth_txmode { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_txmode { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl rte_eth_txmode { - #[inline] - pub fn hw_vlan_reject_tagged(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_reject_tagged(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_reject_untagged(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_reject_untagged(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn hw_vlan_insert_pvid(&self) -> u8 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) } - } - #[inline] - pub fn set_hw_vlan_insert_pvid(&mut self, val: u8) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - hw_vlan_reject_tagged: u8, - hw_vlan_reject_untagged: u8, - hw_vlan_insert_pvid: u8, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let hw_vlan_reject_tagged: u8 = unsafe { ::std::mem::transmute(hw_vlan_reject_tagged) }; - hw_vlan_reject_tagged as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let hw_vlan_reject_untagged: u8 = - unsafe { ::std::mem::transmute(hw_vlan_reject_untagged) }; - hw_vlan_reject_untagged as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let hw_vlan_insert_pvid: u8 = unsafe { ::std::mem::transmute(hw_vlan_insert_pvid) }; - hw_vlan_insert_pvid as u64 - }); - __bindgen_bitfield_unit - } -} -/// A structure used to configure the Receive Side Scaling (RSS) feature -/// of an Ethernet port. -/// If not NULL, the *rss_key* pointer of the *rss_conf* structure points -/// to an array holding the RSS key to use for hashing specific header -/// fields of received packets. The length of this array should be indicated -/// by *rss_key_len* below. Otherwise, a default random hash key is used by -/// the device driver. -/// -/// The *rss_key_len* field of the *rss_conf* structure indicates the length -/// in bytes of the array pointed by *rss_key*. To be compatible, this length -/// will be checked in i40e only. Others assume 40 bytes to be used as before. -/// -/// The *rss_hf* field of the *rss_conf* structure indicates the different -/// types of IPv4/IPv6 packets to which the RSS hashing must be applied. -/// Supplying an *rss_hf* equal to zero disables the RSS feature. -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_rss_conf { - /// < If not NULL, 40-byte hash key. - pub rss_key: *mut u8, - /// < hash key length in bytes. - pub rss_key_len: u8, - /// < Hash functions to apply - see below. - pub rss_hf: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_rss_conf() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(rte_eth_rss_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_rss_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_key as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_key) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_key_len as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_key_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss_hf as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_rss_conf), - "::", - stringify!(rss_hf) - ) - ); -} -impl Clone for rte_eth_rss_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_rss_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(u32)] -/// This enum indicates the possible number of traffic classes -/// in DCB configratioins -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_nb_tcs { - /// < 4 TCs with DCB. - ETH_4_TCS = 4, - /// < 8 TCs with DCB. - ETH_8_TCS = 8, -} -#[repr(u32)] -/// This enum indicates the possible number of queue pools -/// in VMDQ configurations. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_nb_pools { - /// < 8 VMDq pools. - ETH_8_POOLS = 8, - /// < 16 VMDq pools. - ETH_16_POOLS = 16, - /// < 32 VMDq pools. - ETH_32_POOLS = 32, - /// < 64 VMDq pools. - ETH_64_POOLS = 64, -} -/// A structure used to configure the VMDQ+DCB feature -/// of an Ethernet port. -/// -/// Using this feature, packets are routed to a pool of queues, based -/// on the vlan id in the vlan tag, and then to a specific queue within -/// that pool, using the user priority vlan tag field. -/// -/// A default pool may be used, if desired, to route all traffic which -/// does not match the vlan filter rules. -#[repr(C)] -#[derive(Copy)] -pub struct rte_eth_vmdq_dcb_conf { - /// < With DCB, 16 or 32 pools - pub nb_queue_pools: rte_eth_nb_pools, - /// < If non-zero, use a default pool - pub enable_default_pool: u8, - /// < The default pool, if applicable - pub default_pool: u8, - /// < We can have up to 64 filters/mappings - pub nb_pool_maps: u8, - /// < VMDq vlan pool maps. - pub pool_map: [rte_eth_vmdq_dcb_conf__bindgen_ty_1; 64usize], - pub dcb_tc: [u8; 8usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_dcb_conf__bindgen_ty_1 { - /// < The vlan id of the received frame - pub vlan_id: u16, - /// < Bitmask of pools for packet rx - pub pools: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_id as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1), - "::", - stringify!(vlan_id) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).pools as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf__bindgen_ty_1), - "::", - stringify!(pools) - ) - ); -} -impl Clone for rte_eth_vmdq_dcb_conf__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_conf() { - assert_eq!( - ::std::mem::size_of::(), - 1040usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_dcb_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_default_pool as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(enable_default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).default_pool as *const _ as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_pool_maps as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(nb_pool_maps) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool_map as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(pool_map) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 1032usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Clone for rte_eth_vmdq_dcb_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_vmdq_dcb_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_dcb_rx_conf { - /// < Possible DCB TCs, 4 or 8 TCs - pub nb_tcs: rte_eth_nb_tcs, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_dcb_rx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_dcb_rx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_dcb_rx_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_tcs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_rx_conf), - "::", - stringify!(nb_tcs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_rx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Clone for rte_eth_dcb_rx_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_dcb_rx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_dcb_tx_conf { - /// < With DCB, 16 or 32 pools. - pub nb_queue_pools: rte_eth_nb_pools, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_dcb_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_dcb_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_dcb_tx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_tx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_dcb_tx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Clone for rte_eth_vmdq_dcb_tx_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_vmdq_dcb_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_dcb_tx_conf { - /// < Possible DCB TCs, 4 or 8 TCs. - pub nb_tcs: rte_eth_nb_tcs, - /// Traffic class each UP mapped to. - pub dcb_tc: [u8; 8usize], -} -#[test] -fn bindgen_test_layout_rte_eth_dcb_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_dcb_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_dcb_tx_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_tcs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_tx_conf), - "::", - stringify!(nb_tcs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_tc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_dcb_tx_conf), - "::", - stringify!(dcb_tc) - ) - ); -} -impl Clone for rte_eth_dcb_tx_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_dcb_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_tx_conf { - /// < VMDq mode, 64 pools. - pub nb_queue_pools: rte_eth_nb_pools, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_tx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_tx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_tx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_tx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); -} -impl Clone for rte_eth_vmdq_tx_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_vmdq_tx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy)] -pub struct rte_eth_vmdq_rx_conf { - /// < VMDq only mode, 8 or 64 pools - pub nb_queue_pools: rte_eth_nb_pools, - /// < If non-zero, use a default pool - pub enable_default_pool: u8, - /// < The default pool, if applicable - pub default_pool: u8, - /// < Enable VT loop back - pub enable_loop_back: u8, - /// < We can have up to 64 filters/mappings - pub nb_pool_maps: u8, - /// < Flags from ETH_VMDQ_ACCEPT_* - pub rx_mode: u32, - /// < VMDq vlan pool maps. - pub pool_map: [rte_eth_vmdq_rx_conf__bindgen_ty_1; 64usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_vmdq_rx_conf__bindgen_ty_1 { - /// < The vlan id of the received frame - pub vlan_id: u16, - /// < Bitmask of pools for packet rx - pub pools: u64, -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_rx_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_id as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1), - "::", - stringify!(vlan_id) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).pools as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf__bindgen_ty_1), - "::", - stringify!(pools) - ) - ); -} -impl Clone for rte_eth_vmdq_rx_conf__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_eth_vmdq_rx_conf() { - assert_eq!( - ::std::mem::size_of::(), - 1040usize, - concat!("Size of: ", stringify!(rte_eth_vmdq_rx_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_vmdq_rx_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_queue_pools as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(nb_queue_pools) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_default_pool as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(enable_default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).default_pool as *const _ as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(default_pool) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).enable_loop_back as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(enable_loop_back) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_pool_maps as *const _ as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(nb_pool_maps) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_mode as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(rx_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool_map as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_vmdq_rx_conf), - "::", - stringify!(pool_map) - ) - ); -} -impl Clone for rte_eth_vmdq_rx_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_vmdq_rx_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(u32)] -/// Flow Director setting modes: none, signature or perfect. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_mode { - /// < Disable FDIR support. - RTE_FDIR_MODE_NONE = 0, - /// < Enable FDIR signature filter mode. - RTE_FDIR_MODE_SIGNATURE = 1, - /// < Enable FDIR perfect filter mode. - RTE_FDIR_MODE_PERFECT = 2, - /// < Enable FDIR filter mode - MAC VLAN. - RTE_FDIR_MODE_PERFECT_MAC_VLAN = 3, - /// < Enable FDIR filter mode - tunnel. - RTE_FDIR_MODE_PERFECT_TUNNEL = 4, -} -#[repr(u32)] -/// Memory space that can be configured to store Flow Director filters -/// in the board memory. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_pballoc_type { - /// < 64k. - RTE_FDIR_PBALLOC_64K = 0, - /// < 128k. - RTE_FDIR_PBALLOC_128K = 1, - /// < 256k. - RTE_FDIR_PBALLOC_256K = 2, -} -#[repr(u32)] -/// Select report mode of FDIR hash information in RX descriptors. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_fdir_status_mode { - /// < Never report FDIR hash. - RTE_FDIR_NO_REPORT_STATUS = 0, - /// < Only report FDIR hash for matching pkts. - RTE_FDIR_REPORT_STATUS = 1, - /// < Always report FDIR hash. - RTE_FDIR_REPORT_STATUS_ALWAYS = 2, -} -/// A structure used to define the input for IPV4 flow -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_ipv4_flow { - /// < IPv4 source address in big endian. - pub src_ip: u32, - /// < IPv4 destination address in big endian. - pub dst_ip: u32, - /// < Type of service to match. - pub tos: u8, - /// < Time to live to match. - pub ttl: u8, - /// < Protocol, next header in big endian. - pub proto: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_ipv4_flow() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_ipv4_flow)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_ipv4_flow)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_ip as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(src_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_ip as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(dst_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tos as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(tos) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ttl as *const _ as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(ttl) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).proto as *const _ as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv4_flow), - "::", - stringify!(proto) - ) - ); -} -impl Clone for rte_eth_ipv4_flow { - fn clone(&self) -> Self { - *self - } -} -/// A structure used to define the input for IPV6 flow -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_ipv6_flow { - /// < IPv6 source address in big endian. - pub src_ip: [u32; 4usize], - /// < IPv6 destination address in big endian. - pub dst_ip: [u32; 4usize], - /// < Traffic class to match. - pub tc: u8, - /// < Protocol, next header to match. - pub proto: u8, - /// < Hop limits to match. - pub hop_limits: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_ipv6_flow() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_eth_ipv6_flow)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_ipv6_flow)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_ip as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(src_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dst_ip as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(dst_ip) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tc as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(tc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).proto as *const _ as usize }, - 33usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(proto) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).hop_limits as *const _ as usize }, - 34usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_ipv6_flow), - "::", - stringify!(hop_limits) - ) - ); -} -impl Clone for rte_eth_ipv6_flow { - fn clone(&self) -> Self { - *self - } -} -/// A structure used to configure FDIR masks that are used by the device -/// to match the various fields of RX packet headers. -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_masks { - /// < Bit mask for vlan_tci in big endian - pub vlan_tci_mask: u16, - /// Bit mask for ipv4 flow in big endian. - pub ipv4_mask: rte_eth_ipv4_flow, - /// Bit maks for ipv6 flow in big endian. - pub ipv6_mask: rte_eth_ipv6_flow, - /// Bit mask for L4 source port in big endian. - pub src_port_mask: u16, - /// Bit mask for L4 destination port in big endian. - pub dst_port_mask: u16, - /// 6 bit mask for proper 6 bytes of Mac address, bit 0 matches the - /// first byte on the wire - pub mac_addr_byte_mask: u8, - /// Bit mask for tunnel ID in big endian. - pub tunnel_id_mask: u32, - /// < 1 - Match tunnel type, - /// 0 - Ignore tunnel type. - pub tunnel_type_mask: u8, -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_masks() { - assert_eq!( - ::std::mem::size_of::(), - 68usize, - concat!("Size of: ", stringify!(rte_eth_fdir_masks)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_masks)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vlan_tci_mask as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(vlan_tci_mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ipv4_mask as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(ipv4_mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ipv6_mask as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(ipv6_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).src_port_mask as *const _ as usize - }, - 52usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(src_port_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dst_port_mask as *const _ as usize - }, - 54usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(dst_port_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mac_addr_byte_mask as *const _ as usize - }, - 56usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(mac_addr_byte_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tunnel_id_mask as *const _ as usize - }, - 60usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(tunnel_id_mask) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tunnel_type_mask as *const _ as usize - }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_masks), - "::", - stringify!(tunnel_type_mask) - ) - ); -} -impl Clone for rte_eth_fdir_masks { - fn clone(&self) -> Self { - *self - } -} -#[repr(u32)] -/// Payload type -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum rte_eth_payload_type { - RTE_ETH_PAYLOAD_UNKNOWN = 0, - RTE_ETH_RAW_PAYLOAD = 1, - RTE_ETH_L2_PAYLOAD = 2, - RTE_ETH_L3_PAYLOAD = 3, - RTE_ETH_L4_PAYLOAD = 4, - RTE_ETH_PAYLOAD_MAX = 8, -} -/// A structure used to select bytes extracted from the protocol layers to -/// flexible payload for filter -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_flex_payload_cfg { - /// < Payload type - pub type_: rte_eth_payload_type, - pub src_offset: [u16; 16usize], -} -#[test] -fn bindgen_test_layout_rte_eth_flex_payload_cfg() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(rte_eth_flex_payload_cfg)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_flex_payload_cfg)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_flex_payload_cfg), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).src_offset as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_flex_payload_cfg), - "::", - stringify!(src_offset) - ) - ); -} -impl Clone for rte_eth_flex_payload_cfg { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_flex_payload_cfg { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to define FDIR masks for flexible payload -/// for each flow type -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_flex_mask { - pub flow_type: u16, - pub mask: [u8; 16usize], -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_flex_mask() { - assert_eq!( - ::std::mem::size_of::(), - 18usize, - concat!("Size of: ", stringify!(rte_eth_fdir_flex_mask)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_flex_mask)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).flow_type as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_mask), - "::", - stringify!(flow_type) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_mask), - "::", - stringify!(mask) - ) - ); -} -impl Clone for rte_eth_fdir_flex_mask { - fn clone(&self) -> Self { - *self - } -} -/// A structure used to define all flexible payload related setting -/// include flex payload and flex mask -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_fdir_flex_conf { - /// < The number of following payload cfg - pub nb_payloads: u16, - /// < The number of following mask - pub nb_flexmasks: u16, - pub flex_set: [rte_eth_flex_payload_cfg; 8usize], - pub flex_mask: [rte_eth_fdir_flex_mask; 22usize], -} -#[test] -fn bindgen_test_layout_rte_eth_fdir_flex_conf() { - assert_eq!( - ::std::mem::size_of::(), - 688usize, - concat!("Size of: ", stringify!(rte_eth_fdir_flex_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_fdir_flex_conf)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_payloads as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(nb_payloads) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).nb_flexmasks as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(nb_flexmasks) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).flex_set as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(flex_set) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).flex_mask as *const _ as usize - }, - 292usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_fdir_flex_conf), - "::", - stringify!(flex_mask) - ) - ); -} -impl Clone for rte_eth_fdir_flex_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_fdir_flex_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to configure the Flow Director (FDIR) feature -/// of an Ethernet port. -/// -/// If mode is RTE_FDIR_DISABLE, the pballoc value is ignored. -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct rte_fdir_conf { - /// < Flow Director mode. - pub mode: rte_fdir_mode, - /// < Space for FDIR filters. - pub pballoc: rte_fdir_pballoc_type, - /// < How to report FDIR hash. - pub status: rte_fdir_status_mode, - /// RX queue of packets matching a "drop" filter in perfect mode. - pub drop_queue: u8, - pub mask: rte_eth_fdir_masks, - pub flex_conf: rte_eth_fdir_flex_conf, -} -#[test] -fn bindgen_test_layout_rte_fdir_conf() { - assert_eq!( - ::std::mem::size_of::(), - 772usize, - concat!("Size of: ", stringify!(rte_fdir_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_fdir_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mode as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pballoc as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(pballoc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).status as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(status) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).drop_queue as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(drop_queue) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).flex_conf as *const _ as usize }, - 84usize, - concat!( - "Offset of field: ", - stringify!(rte_fdir_conf), - "::", - stringify!(flex_conf) - ) - ); -} -impl Clone for rte_fdir_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_fdir_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// A structure used to enable/disable specific device interrupts. -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_intr_conf { - /// enable/disable lsc interrupt. 0 (default) - disable, 1 enable - pub lsc: u16, - /// enable/disable rxq interrupt. 0 (default) - disable, 1 enable - pub rxq: u16, -} -#[test] -fn bindgen_test_layout_rte_intr_conf() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_intr_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_intr_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lsc as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_intr_conf), - "::", - stringify!(lsc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rxq as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_intr_conf), - "::", - stringify!(rxq) - ) - ); -} -impl Clone for rte_intr_conf { - fn clone(&self) -> Self { - *self - } -} -/// A structure used to configure an Ethernet port. -/// Depending upon the RX multi-queue mode, extra advanced -/// configuration settings may be needed. -#[repr(C)] -#[derive(Copy)] -pub struct rte_eth_conf { - /// < bitmap of ETH_LINK_SPEED_XXX of speeds to be - /// used. ETH_LINK_SPEED_FIXED disables link - /// autonegotiation, and a unique speed shall be - /// set. Otherwise, the bitmap defines the set of - /// speeds to be advertised. If the special value - /// ETH_LINK_SPEED_AUTONEG (0) is used, all speeds - /// supported are advertised. - pub link_speeds: u32, - /// < Port RX configuration. - pub rxmode: rte_eth_rxmode, - /// < Port TX configuration. - pub txmode: rte_eth_txmode, - /// < Loopback operation mode. By default the value - /// is 0, meaning the loopback mode is disabled. - /// Read the datasheet of given ethernet controller - /// for details. The possible values of this field - /// are defined in implementation of each driver. - pub lpbk_mode: u32, - /// < Port RX filtering configuration (union). - pub rx_adv_conf: rte_eth_conf__bindgen_ty_1, - /// < Port TX DCB configuration (union). - pub tx_adv_conf: rte_eth_conf__bindgen_ty_2, - /// Currently,Priority Flow Control(PFC) are supported,if DCB with PFC - /// is needed,and the variable must be set ETH_DCB_PFC_SUPPORT. - pub dcb_capability_en: u32, - /// < FDIR configuration. - pub fdir_conf: rte_fdir_conf, - /// < Interrupt mode configuration. - pub intr_conf: rte_intr_conf, -} -#[repr(C)] -#[derive(Copy)] -pub struct rte_eth_conf__bindgen_ty_1 { - /// < Port RSS configuration - pub rss_conf: rte_eth_rss_conf, - pub vmdq_dcb_conf: rte_eth_vmdq_dcb_conf, - pub dcb_rx_conf: rte_eth_dcb_rx_conf, - pub vmdq_rx_conf: rte_eth_vmdq_rx_conf, -} -#[test] -fn bindgen_test_layout_rte_eth_conf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2120usize, - concat!("Size of: ", stringify!(rte_eth_conf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_conf__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).rss_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(rss_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_dcb_conf as *const _ - as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(vmdq_dcb_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dcb_rx_conf as *const _ as usize - }, - 1064usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(dcb_rx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_rx_conf as *const _ as usize - }, - 1080usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_1), - "::", - stringify!(vmdq_rx_conf) - ) - ); -} -impl Clone for rte_eth_conf__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_conf__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_eth_conf__bindgen_ty_2 { - pub vmdq_dcb_tx_conf: __BindgenUnionField, - pub dcb_tx_conf: __BindgenUnionField, - pub vmdq_tx_conf: __BindgenUnionField, - pub bindgen_union_field: [u32; 3usize], -} -#[test] -fn bindgen_test_layout_rte_eth_conf__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(rte_eth_conf__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_eth_conf__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_dcb_tx_conf as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(vmdq_dcb_tx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).dcb_tx_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(dcb_tx_conf) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).vmdq_tx_conf as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf__bindgen_ty_2), - "::", - stringify!(vmdq_tx_conf) - ) - ); -} -impl Clone for rte_eth_conf__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_eth_conf() { - assert_eq!( - ::std::mem::size_of::(), - 2944usize, - concat!("Size of: ", stringify!(rte_eth_conf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_eth_conf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).link_speeds as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(link_speeds) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rxmode as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(rxmode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).txmode as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(txmode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lpbk_mode as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(lpbk_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_adv_conf as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(rx_adv_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tx_adv_conf as *const _ as usize }, - 2152usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(tx_adv_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).dcb_capability_en as *const _ as usize }, - 2164usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(dcb_capability_en) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fdir_conf as *const _ as usize }, - 2168usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(fdir_conf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).intr_conf as *const _ as usize }, - 2940usize, - concat!( - "Offset of field: ", - stringify!(rte_eth_conf), - "::", - stringify!(intr_conf) - ) - ); -} -impl Clone for rte_eth_conf { - fn clone(&self) -> Self { - *self - } -} -impl Default for rte_eth_conf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/layout_kni_mbuf.rs b/tests/expectations/tests/layout_kni_mbuf.rs deleted file mode 100644 index 80ab1be9a8..0000000000 --- a/tests/expectations/tests/layout_kni_mbuf.rs +++ /dev/null @@ -1,184 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const RTE_CACHE_LINE_MIN_SIZE: u32 = 64; -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_kni_mbuf { - pub buf_addr: *mut ::std::os::raw::c_void, - pub buf_physaddr: u64, - pub pad0: [::std::os::raw::c_char; 2usize], - /// < Start address of data in segment buffer. - pub data_off: u16, - pub pad1: [::std::os::raw::c_char; 2usize], - /// < Number of segments. - pub nb_segs: u8, - pub pad4: [::std::os::raw::c_char; 1usize], - /// < Offload features. - pub ol_flags: u64, - pub pad2: [::std::os::raw::c_char; 4usize], - /// < Total pkt len: sum of all segment data_len. - pub pkt_len: u32, - /// < Amount of data in segment buffer. - pub data_len: u16, - pub __bindgen_padding_0: [u8; 22usize], - pub pad3: [::std::os::raw::c_char; 8usize], - pub pool: *mut ::std::os::raw::c_void, - pub next: *mut ::std::os::raw::c_void, - pub __bindgen_padding_1: [u64; 5usize], -} -#[test] -fn bindgen_test_layout_rte_kni_mbuf() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(rte_kni_mbuf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(buf_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_physaddr as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(buf_physaddr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pad0 as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pad0) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_off as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(data_off) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pad1 as *const _ as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pad1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_segs as *const _ as usize }, - 22usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(nb_segs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pad4 as *const _ as usize }, - 23usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pad4) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ol_flags as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(ol_flags) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pad2 as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pad2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pkt_len as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pkt_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_len as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(data_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pad3 as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pad3) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(pool) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).next as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(rte_kni_mbuf), - "::", - stringify!(next) - ) - ); -} -impl Default for rte_kni_mbuf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/layout_large_align_field.rs b/tests/expectations/tests/layout_large_align_field.rs deleted file mode 100644 index af738d04d8..0000000000 --- a/tests/expectations/tests/layout_large_align_field.rs +++ /dev/null @@ -1,614 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -pub const RTE_LIBRTE_IP_FRAG_MAX_FRAG: u32 = 4; -pub const IP_LAST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_LAST_FRAG_IDX; -pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX; -pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM; -pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - /// < index of last fragment - IP_LAST_FRAG_IDX = 0, - /// < index of first fragment - IP_FIRST_FRAG_IDX = 1, - /// < minimum number of fragments - IP_MIN_FRAG_NUM = 2, - IP_MAX_FRAG_NUM = 4, -} -/// @internal fragmented mbuf -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ip_frag { - /// < offset into the packet - pub ofs: u16, - /// < length of fragment - pub len: u16, - /// < fragment mbuf - pub mb: *mut rte_mbuf, -} -#[test] -fn bindgen_test_layout_ip_frag() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ip_frag)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ofs as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(ofs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).len as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mb as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_frag), - "::", - stringify!(mb) - ) - ); -} -impl Default for ip_frag { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// @internal to uniquely indetify fragmented datagram. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct ip_frag_key { - /// < src address, first 8 bytes used for IPv4 - pub src_dst: [u64; 4usize], - /// < dst address - pub id: u32, - /// < src/dst key length - pub key_len: u32, -} -#[test] -fn bindgen_test_layout_ip_frag_key() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(ip_frag_key)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag_key)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).src_dst as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(src_dst) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(id) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).key_len as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_key), - "::", - stringify!(key_len) - ) - ); -} -/// @internal Fragmented packet to reassemble. -/// First two entries in the frags[] array are for the last and first fragments. -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ip_frag_pkt { - /// < LRU list - pub lru: ip_frag_pkt__bindgen_ty_1, - /// < fragmentation key - pub key: ip_frag_key, - /// < creation timestamp - pub start: u64, - /// < expected reassembled size - pub total_size: u32, - /// < size of fragments received - pub frag_size: u32, - /// < index of next entry to fill - pub last_idx: u32, - /// < fragments - pub frags: [ip_frag; 4usize], - pub __bindgen_padding_0: [u64; 6usize], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ip_frag_pkt__bindgen_ty_1 { - pub tqe_next: *mut ip_frag_pkt, - pub tqe_prev: *mut *mut ip_frag_pkt, -} -#[test] -fn bindgen_test_layout_ip_frag_pkt__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ip_frag_pkt__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_frag_pkt__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tqe_next as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt__bindgen_ty_1), - "::", - stringify!(tqe_next) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tqe_prev as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt__bindgen_ty_1), - "::", - stringify!(tqe_prev) - ) - ); -} -impl Default for ip_frag_pkt__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_ip_frag_pkt() { - assert_eq!( - ::std::mem::size_of::(), - 192usize, - concat!("Size of: ", stringify!(ip_frag_pkt)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lru as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(lru) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).key as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(key) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).start as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(start) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).total_size as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(total_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).frag_size as *const _ as usize }, - 68usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(frag_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).last_idx as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(last_idx) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).frags as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_pkt), - "::", - stringify!(frags) - ) - ); -} -impl Default for ip_frag_pkt { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ip_pkt_list { - pub tqh_first: *mut ip_frag_pkt, - pub tqh_last: *mut *mut ip_frag_pkt, -} -#[test] -fn bindgen_test_layout_ip_pkt_list() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ip_pkt_list)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ip_pkt_list)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tqh_first as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_pkt_list), - "::", - stringify!(tqh_first) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tqh_last as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_pkt_list), - "::", - stringify!(tqh_last) - ) - ); -} -impl Default for ip_pkt_list { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// fragmentation table statistics -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ip_frag_tbl_stat { - /// < total # of find/insert attempts. - pub find_num: u64, - /// < # of add ops. - pub add_num: u64, - /// < # of del ops. - pub del_num: u64, - /// < # of reuse (del/add) ops. - pub reuse_num: u64, - /// < total # of add failures. - pub fail_total: u64, - /// < # of 'no space' add failures. - pub fail_nospace: u64, - pub __bindgen_padding_0: [u64; 2usize], -} -#[test] -fn bindgen_test_layout_ip_frag_tbl_stat() { - assert_eq!( - ::std::mem::size_of::(), - 64usize, - concat!("Size of: ", stringify!(ip_frag_tbl_stat)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).find_num as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(find_num) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).add_num as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(add_num) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).del_num as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(del_num) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).reuse_num as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(reuse_num) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fail_total as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(fail_total) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fail_nospace as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(ip_frag_tbl_stat), - "::", - stringify!(fail_nospace) - ) - ); -} -impl Default for ip_frag_tbl_stat { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// fragmentation table -#[repr(C)] -pub struct rte_ip_frag_tbl { - /// < ttl for table entries. - pub max_cycles: u64, - /// < hash value mask. - pub entry_mask: u32, - /// < max entries allowed. - pub max_entries: u32, - /// < entries in use. - pub use_entries: u32, - /// < hash assocaitivity. - pub bucket_entries: u32, - /// < total size of the table. - pub nb_entries: u32, - /// < num of associativity lines. - pub nb_buckets: u32, - /// < last used entry. - pub last: *mut ip_frag_pkt, - /// < LRU list for table entries. - pub lru: ip_pkt_list, - pub __bindgen_padding_0: u64, - /// < statistics counters. - pub stat: ip_frag_tbl_stat, - /// < hash table. - pub pkt: __IncompleteArrayField, -} -#[test] -fn bindgen_test_layout_rte_ip_frag_tbl() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(rte_ip_frag_tbl)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).max_cycles as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(max_cycles) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).entry_mask as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(entry_mask) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).max_entries as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(max_entries) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).use_entries as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(use_entries) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bucket_entries as *const _ as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(bucket_entries) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_entries as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(nb_entries) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_buckets as *const _ as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(nb_buckets) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).last as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(last) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).lru as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(lru) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).stat as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(stat) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pkt as *const _ as usize }, - 128usize, - concat!( - "Offset of field: ", - stringify!(rte_ip_frag_tbl), - "::", - stringify!(pkt) - ) - ); -} -impl Default for rte_ip_frag_tbl { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// < fragment mbuf -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct rte_mbuf { - pub _address: u8, -} diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs deleted file mode 100644 index c42cd0bad1..0000000000 --- a/tests/expectations/tests/layout_mbuf.rs +++ /dev/null @@ -1,1110 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -pub const RTE_CACHE_LINE_MIN_SIZE: u32 = 64; -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -pub type phys_addr_t = u64; -pub type MARKER = [*mut ::std::os::raw::c_void; 0usize]; -pub type MARKER8 = [u8; 0usize]; -pub type MARKER64 = [u64; 0usize]; -/// The atomic counter structure. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_atomic16_t { - /// < An internal counter value. - pub cnt: i16, -} -#[test] -fn bindgen_test_layout_rte_atomic16_t() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(rte_atomic16_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_atomic16_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cnt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_atomic16_t), - "::", - stringify!(cnt) - ) - ); -} -/// The generic rte_mbuf, containing a packet mbuf. -#[repr(C)] -pub struct rte_mbuf { - pub cacheline0: MARKER, - /// < Virtual address of segment buffer. - pub buf_addr: *mut ::std::os::raw::c_void, - /// < Physical address of segment buffer. - pub buf_physaddr: phys_addr_t, - /// < Length of segment buffer. - pub buf_len: u16, - pub rearm_data: MARKER8, - pub data_off: u16, - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, - /// < Number of segments. - pub nb_segs: u8, - /// < Input port. - pub port: u8, - /// < Offload features. - pub ol_flags: u64, - pub rx_descriptor_fields1: MARKER, - pub __bindgen_anon_2: rte_mbuf__bindgen_ty_2, - /// < Total pkt len: sum of all segments. - pub pkt_len: u32, - /// < Amount of data in segment buffer. - pub data_len: u16, - /// VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. - pub vlan_tci: u16, - /// < hash information - pub hash: rte_mbuf__bindgen_ty_3, - /// < Sequence number. See also rte_reorder_insert() - pub seqn: u32, - /// Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. - pub vlan_tci_outer: u16, - pub cacheline1: MARKER, - pub __bindgen_anon_3: rte_mbuf__bindgen_ty_4, - /// < Pool from which mbuf was allocated. - pub pool: *mut rte_mempool, - /// < Next segment of scattered packet. - pub next: *mut rte_mbuf, - pub __bindgen_anon_4: rte_mbuf__bindgen_ty_5, - /// Size of the application private data. In case of an indirect - /// mbuf, it stores the direct mbuf private data size. - pub priv_size: u16, - /// Timesync flags for use with IEEE1588. - pub timesync: u16, - pub __bindgen_padding_0: [u32; 7usize], -} -/// 16-bit Reference counter. -/// It should only be accessed using the following functions: -/// rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and -/// rte_mbuf_refcnt_set(). The functionality of these functions (atomic, -/// or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC -/// config option. -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_1 { - /// < Atomically accessed refcnt - pub refcnt_atomic: rte_atomic16_t, - /// < Non-atomically accessed refcnt - pub refcnt: u16, - _bindgen_union_align: u16, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).refcnt_atomic as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_1), - "::", - stringify!(refcnt_atomic) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).refcnt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_1), - "::", - stringify!(refcnt) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_2 { - /// < L2/L3/L4 and tunnel information. - pub packet_type: u32, - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_2__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u8>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_2__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_2__bindgen_ty_1) - ) - ); -} -impl rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - #[inline] - pub fn l2_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } - } - #[inline] - pub fn set_l2_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 4u8, val as u64) - } - } - #[inline] - pub fn l3_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } - } - #[inline] - pub fn set_l3_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 4u8, val as u64) - } - } - #[inline] - pub fn l4_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u32) } - } - #[inline] - pub fn set_l4_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 4u8, val as u64) - } - } - #[inline] - pub fn tun_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 4u8) as u32) } - } - #[inline] - pub fn set_tun_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(12usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l2_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l2_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l3_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l3_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(20usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l4_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l4_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 4u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - l2_type: u32, - l3_type: u32, - l4_type: u32, - tun_type: u32, - inner_l2_type: u32, - inner_l3_type: u32, - inner_l4_type: u32, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 4u8, { - let l2_type: u32 = unsafe { ::std::mem::transmute(l2_type) }; - l2_type as u64 - }); - __bindgen_bitfield_unit.set(4usize, 4u8, { - let l3_type: u32 = unsafe { ::std::mem::transmute(l3_type) }; - l3_type as u64 - }); - __bindgen_bitfield_unit.set(8usize, 4u8, { - let l4_type: u32 = unsafe { ::std::mem::transmute(l4_type) }; - l4_type as u64 - }); - __bindgen_bitfield_unit.set(12usize, 4u8, { - let tun_type: u32 = unsafe { ::std::mem::transmute(tun_type) }; - tun_type as u64 - }); - __bindgen_bitfield_unit.set(16usize, 4u8, { - let inner_l2_type: u32 = unsafe { ::std::mem::transmute(inner_l2_type) }; - inner_l2_type as u64 - }); - __bindgen_bitfield_unit.set(20usize, 4u8, { - let inner_l3_type: u32 = unsafe { ::std::mem::transmute(inner_l3_type) }; - inner_l3_type as u64 - }); - __bindgen_bitfield_unit.set(24usize, 4u8, { - let inner_l4_type: u32 = unsafe { ::std::mem::transmute(inner_l4_type) }; - inner_l4_type as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).packet_type as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_2), - "::", - stringify!(packet_type) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_3 { - /// < RSS hash result if RSS enabled - pub rss: u32, - /// < Filter identifier if FDIR enabled - pub fdir: rte_mbuf__bindgen_ty_3__bindgen_ty_1, - /// < Hierarchical scheduler - pub sched: rte_mbuf__bindgen_ty_3__bindgen_ty_2, - /// < User defined tags. See rte_distributor_process() - pub usr: u32, - _bindgen_union_align: [u32; 2usize], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1 { - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1, - pub hi: u32, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, - pub lo: u32, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { - pub hash: u16, - pub id: u16, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::< - rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, - >())) - .hash as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(hash) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::< - rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, - >())) - .id as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(id) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lo - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(lo) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).hi as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1), - "::", - stringify!(hi) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_3__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_2 { - pub lo: u32, - pub hi: u32, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lo as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2), - "::", - stringify!(lo) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).hi as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2), - "::", - stringify!(hi) - ) - ); -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_3)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_3)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(rss) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fdir as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(fdir) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).sched as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(sched) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).usr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(usr) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_3 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_4 { - /// < Can be used for external metadata - pub userdata: *mut ::std::os::raw::c_void, - /// < Allow 8-byte userdata on 32-bit - pub udata64: u64, - _bindgen_union_align: u64, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_4() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_4)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).userdata as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_4), - "::", - stringify!(userdata) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).udata64 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_4), - "::", - stringify!(udata64) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_4 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_5 { - /// < combined for easy fetch - pub tx_offload: u64, - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_5__bindgen_ty_1, - _bindgen_union_align: u64, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u16>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_5__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_5__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_5__bindgen_ty_1) - ) - ); -} -impl rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - #[inline] - pub fn l2_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u64) } - } - #[inline] - pub fn set_l2_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 7u8, val as u64) - } - } - #[inline] - pub fn l3_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 9u8) as u64) } - } - #[inline] - pub fn set_l3_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 9u8, val as u64) - } - } - #[inline] - pub fn l4_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u64) } - } - #[inline] - pub fn set_l4_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 8u8, val as u64) - } - } - #[inline] - pub fn tso_segsz(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 16u8) as u64) } - } - #[inline] - pub fn set_tso_segsz(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 16u8, val as u64) - } - } - #[inline] - pub fn outer_l3_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 9u8) as u64) } - } - #[inline] - pub fn set_outer_l3_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(40usize, 9u8, val as u64) - } - } - #[inline] - pub fn outer_l2_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(49usize, 7u8) as u64) } - } - #[inline] - pub fn set_outer_l2_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(49usize, 7u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - l2_len: u64, - l3_len: u64, - l4_len: u64, - tso_segsz: u64, - outer_l3_len: u64, - outer_l2_len: u64, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u16> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u16> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 7u8, { - let l2_len: u64 = unsafe { ::std::mem::transmute(l2_len) }; - l2_len as u64 - }); - __bindgen_bitfield_unit.set(7usize, 9u8, { - let l3_len: u64 = unsafe { ::std::mem::transmute(l3_len) }; - l3_len as u64 - }); - __bindgen_bitfield_unit.set(16usize, 8u8, { - let l4_len: u64 = unsafe { ::std::mem::transmute(l4_len) }; - l4_len as u64 - }); - __bindgen_bitfield_unit.set(24usize, 16u8, { - let tso_segsz: u64 = unsafe { ::std::mem::transmute(tso_segsz) }; - tso_segsz as u64 - }); - __bindgen_bitfield_unit.set(40usize, 9u8, { - let outer_l3_len: u64 = unsafe { ::std::mem::transmute(outer_l3_len) }; - outer_l3_len as u64 - }); - __bindgen_bitfield_unit.set(49usize, 7u8, { - let outer_l2_len: u64 = unsafe { ::std::mem::transmute(outer_l2_len) }; - outer_l2_len as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_5() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_5)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_5)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tx_offload as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_5), - "::", - stringify!(tx_offload) - ) - ); -} -impl Default for rte_mbuf__bindgen_ty_5 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_rte_mbuf() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(rte_mbuf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cacheline0 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(cacheline0) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_physaddr as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_physaddr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_len as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rearm_data as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(rearm_data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_off as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(data_off) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_segs as *const _ as usize }, - 22usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(nb_segs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).port as *const _ as usize }, - 23usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(port) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ol_flags as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(ol_flags) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_descriptor_fields1 as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(rx_descriptor_fields1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pkt_len as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(pkt_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_len as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(data_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).vlan_tci as *const _ as usize }, - 42usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(vlan_tci) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).hash as *const _ as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(hash) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).seqn as *const _ as usize }, - 52usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(seqn) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).vlan_tci_outer as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(vlan_tci_outer) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cacheline1 as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(cacheline1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(pool) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).next as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(next) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).priv_size as *const _ as usize }, - 96usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(priv_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).timesync as *const _ as usize }, - 98usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(timesync) - ) - ); -} -impl Default for rte_mbuf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// < Pool from which mbuf was allocated. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct rte_mempool { - pub _address: u8, -} diff --git a/tests/expectations/tests/layout_mbuf_1_0.rs b/tests/expectations/tests/layout_mbuf_1_0.rs deleted file mode 100644 index 2fd5141897..0000000000 --- a/tests/expectations/tests/layout_mbuf_1_0.rs +++ /dev/null @@ -1,1184 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -pub const RTE_CACHE_LINE_MIN_SIZE: u32 = 64; -pub const RTE_CACHE_LINE_SIZE: u32 = 64; -pub type phys_addr_t = u64; -pub type MARKER = [*mut ::std::os::raw::c_void; 0usize]; -pub type MARKER8 = [u8; 0usize]; -pub type MARKER64 = [u64; 0usize]; -/// The atomic counter structure. -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_atomic16_t { - /// < An internal counter value. - pub cnt: i16, -} -#[test] -fn bindgen_test_layout_rte_atomic16_t() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(rte_atomic16_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_atomic16_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cnt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_atomic16_t), - "::", - stringify!(cnt) - ) - ); -} -impl Clone for rte_atomic16_t { - fn clone(&self) -> Self { - *self - } -} -/// The generic rte_mbuf, containing a packet mbuf. -#[repr(C)] -pub struct rte_mbuf { - pub cacheline0: MARKER, - /// < Virtual address of segment buffer. - pub buf_addr: *mut ::std::os::raw::c_void, - /// < Physical address of segment buffer. - pub buf_physaddr: phys_addr_t, - /// < Length of segment buffer. - pub buf_len: u16, - pub rearm_data: MARKER8, - pub data_off: u16, - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, - /// < Number of segments. - pub nb_segs: u8, - /// < Input port. - pub port: u8, - /// < Offload features. - pub ol_flags: u64, - pub rx_descriptor_fields1: MARKER, - pub __bindgen_anon_2: rte_mbuf__bindgen_ty_2, - /// < Total pkt len: sum of all segments. - pub pkt_len: u32, - /// < Amount of data in segment buffer. - pub data_len: u16, - /// VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. - pub vlan_tci: u16, - /// < hash information - pub hash: rte_mbuf__bindgen_ty_3, - /// < Sequence number. See also rte_reorder_insert() - pub seqn: u32, - /// Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. - pub vlan_tci_outer: u16, - pub cacheline1: MARKER, - pub __bindgen_anon_3: rte_mbuf__bindgen_ty_4, - /// < Pool from which mbuf was allocated. - pub pool: *mut rte_mempool, - /// < Next segment of scattered packet. - pub next: *mut rte_mbuf, - pub __bindgen_anon_4: rte_mbuf__bindgen_ty_5, - /// Size of the application private data. In case of an indirect - /// mbuf, it stores the direct mbuf private data size. - pub priv_size: u16, - /// Timesync flags for use with IEEE1588. - pub timesync: u16, - pub __bindgen_padding_0: [u32; 7usize], -} -/// 16-bit Reference counter. -/// It should only be accessed using the following functions: -/// rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and -/// rte_mbuf_refcnt_set(). The functionality of these functions (atomic, -/// or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC -/// config option. -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_1 { - /// < Atomically accessed refcnt - pub refcnt_atomic: __BindgenUnionField, - /// < Non-atomically accessed refcnt - pub refcnt: __BindgenUnionField, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).refcnt_atomic as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_1), - "::", - stringify!(refcnt_atomic) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).refcnt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_1), - "::", - stringify!(refcnt) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_2 { - /// < L2/L3/L4 and tunnel information. - pub packet_type: __BindgenUnionField, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u8>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_2__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_2__bindgen_ty_1) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -impl rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - #[inline] - pub fn l2_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) } - } - #[inline] - pub fn set_l2_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 4u8, val as u64) - } - } - #[inline] - pub fn l3_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) } - } - #[inline] - pub fn set_l3_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(4usize, 4u8, val as u64) - } - } - #[inline] - pub fn l4_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 4u8) as u32) } - } - #[inline] - pub fn set_l4_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(8usize, 4u8, val as u64) - } - } - #[inline] - pub fn tun_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 4u8) as u32) } - } - #[inline] - pub fn set_tun_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(12usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l2_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l2_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l3_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l3_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(20usize, 4u8, val as u64) - } - } - #[inline] - pub fn inner_l4_type(&self) -> u32 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 4u8) as u32) } - } - #[inline] - pub fn set_inner_l4_type(&mut self, val: u32) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 4u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - l2_type: u32, - l3_type: u32, - l4_type: u32, - tun_type: u32, - inner_l2_type: u32, - inner_l3_type: u32, - inner_l4_type: u32, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 4u8, { - let l2_type: u32 = unsafe { ::std::mem::transmute(l2_type) }; - l2_type as u64 - }); - __bindgen_bitfield_unit.set(4usize, 4u8, { - let l3_type: u32 = unsafe { ::std::mem::transmute(l3_type) }; - l3_type as u64 - }); - __bindgen_bitfield_unit.set(8usize, 4u8, { - let l4_type: u32 = unsafe { ::std::mem::transmute(l4_type) }; - l4_type as u64 - }); - __bindgen_bitfield_unit.set(12usize, 4u8, { - let tun_type: u32 = unsafe { ::std::mem::transmute(tun_type) }; - tun_type as u64 - }); - __bindgen_bitfield_unit.set(16usize, 4u8, { - let inner_l2_type: u32 = unsafe { ::std::mem::transmute(inner_l2_type) }; - inner_l2_type as u64 - }); - __bindgen_bitfield_unit.set(20usize, 4u8, { - let inner_l3_type: u32 = unsafe { ::std::mem::transmute(inner_l3_type) }; - inner_l3_type as u64 - }); - __bindgen_bitfield_unit.set(24usize, 4u8, { - let inner_l4_type: u32 = unsafe { ::std::mem::transmute(inner_l4_type) }; - inner_l4_type as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).packet_type as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_2), - "::", - stringify!(packet_type) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3 { - /// < RSS hash result if RSS enabled - pub rss: __BindgenUnionField, - /// < Filter identifier if FDIR enabled - pub fdir: __BindgenUnionField, - /// < Hierarchical scheduler - pub sched: __BindgenUnionField, - /// < User defined tags. See rte_distributor_process() - pub usr: __BindgenUnionField, - pub bindgen_union_field: [u32; 2usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1 { - pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1, - pub hi: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { - pub __bindgen_anon_1: - __BindgenUnionField, - pub lo: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { - pub hash: u16, - pub id: u16, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::< - rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, - >())) - .hash as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(hash) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::< - rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, - >())) - .id as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(id) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lo - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(lo) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).hi as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_1), - "::", - stringify!(hi) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_3__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_3__bindgen_ty_2 { - pub lo: u32, - pub hi: u32, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lo as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2), - "::", - stringify!(lo) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).hi as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3__bindgen_ty_2), - "::", - stringify!(hi) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_3__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_3() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_3)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_3)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rss as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(rss) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fdir as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(fdir) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).sched as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(sched) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).usr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_3), - "::", - stringify!(usr) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_3 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_4 { - /// < Can be used for external metadata - pub userdata: __BindgenUnionField<*mut ::std::os::raw::c_void>, - /// < Allow 8-byte userdata on 32-bit - pub udata64: __BindgenUnionField, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_4() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_4)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).userdata as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_4), - "::", - stringify!(userdata) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).udata64 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_4), - "::", - stringify!(udata64) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_4 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_5 { - /// < combined for easy fetch - pub tx_offload: __BindgenUnionField, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u16>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_5__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of: ", - stringify!(rte_mbuf__bindgen_ty_5__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(rte_mbuf__bindgen_ty_5__bindgen_ty_1) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -impl rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - #[inline] - pub fn l2_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u64) } - } - #[inline] - pub fn set_l2_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 7u8, val as u64) - } - } - #[inline] - pub fn l3_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 9u8) as u64) } - } - #[inline] - pub fn set_l3_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 9u8, val as u64) - } - } - #[inline] - pub fn l4_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u64) } - } - #[inline] - pub fn set_l4_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 8u8, val as u64) - } - } - #[inline] - pub fn tso_segsz(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 16u8) as u64) } - } - #[inline] - pub fn set_tso_segsz(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 16u8, val as u64) - } - } - #[inline] - pub fn outer_l3_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 9u8) as u64) } - } - #[inline] - pub fn set_outer_l3_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(40usize, 9u8, val as u64) - } - } - #[inline] - pub fn outer_l2_len(&self) -> u64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(49usize, 7u8) as u64) } - } - #[inline] - pub fn set_outer_l2_len(&mut self, val: u64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(49usize, 7u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - l2_len: u64, - l3_len: u64, - l4_len: u64, - tso_segsz: u64, - outer_l3_len: u64, - outer_l2_len: u64, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u16> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u16> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 7u8, { - let l2_len: u64 = unsafe { ::std::mem::transmute(l2_len) }; - l2_len as u64 - }); - __bindgen_bitfield_unit.set(7usize, 9u8, { - let l3_len: u64 = unsafe { ::std::mem::transmute(l3_len) }; - l3_len as u64 - }); - __bindgen_bitfield_unit.set(16usize, 8u8, { - let l4_len: u64 = unsafe { ::std::mem::transmute(l4_len) }; - l4_len as u64 - }); - __bindgen_bitfield_unit.set(24usize, 16u8, { - let tso_segsz: u64 = unsafe { ::std::mem::transmute(tso_segsz) }; - tso_segsz as u64 - }); - __bindgen_bitfield_unit.set(40usize, 9u8, { - let outer_l3_len: u64 = unsafe { ::std::mem::transmute(outer_l3_len) }; - outer_l3_len as u64 - }); - __bindgen_bitfield_unit.set(49usize, 7u8, { - let outer_l2_len: u64 = unsafe { ::std::mem::transmute(outer_l2_len) }; - outer_l2_len as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_rte_mbuf__bindgen_ty_5() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(rte_mbuf__bindgen_ty_5)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(rte_mbuf__bindgen_ty_5)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).tx_offload as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf__bindgen_ty_5), - "::", - stringify!(tx_offload) - ) - ); -} -impl Clone for rte_mbuf__bindgen_ty_5 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_rte_mbuf() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(rte_mbuf)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cacheline0 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(cacheline0) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_addr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_addr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_physaddr as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_physaddr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).buf_len as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(buf_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rearm_data as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(rearm_data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_off as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(data_off) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).nb_segs as *const _ as usize }, - 22usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(nb_segs) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).port as *const _ as usize }, - 23usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(port) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ol_flags as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(ol_flags) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rx_descriptor_fields1 as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(rx_descriptor_fields1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pkt_len as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(pkt_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).data_len as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(data_len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).vlan_tci as *const _ as usize }, - 42usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(vlan_tci) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).hash as *const _ as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(hash) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).seqn as *const _ as usize }, - 52usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(seqn) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).vlan_tci_outer as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(vlan_tci_outer) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cacheline1 as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(cacheline1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).pool as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(pool) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).next as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(next) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).priv_size as *const _ as usize }, - 96usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(priv_size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).timesync as *const _ as usize }, - 98usize, - concat!( - "Offset of field: ", - stringify!(rte_mbuf), - "::", - stringify!(timesync) - ) - ); -} -impl Default for rte_mbuf { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// < Pool from which mbuf was allocated. -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct rte_mempool { - pub _address: u8, -} -impl Clone for rte_mempool { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/libclang-3.8/auto.rs b/tests/expectations/tests/libclang-3.8/auto.rs deleted file mode 100644 index 8db72d0fa8..0000000000 --- a/tests/expectations/tests/libclang-3.8/auto.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4kFooE"] - pub static mut Foo_kFoo: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_Z5Test2v"] - pub fn Test2() -> ::std::os::raw::c_uint; -} diff --git a/tests/expectations/tests/libclang-3.8/call-conv-field.rs b/tests/expectations/tests/libclang-3.8/call-conv-field.rs deleted file mode 100644 index bad20dea8b..0000000000 --- a/tests/expectations/tests/libclang-3.8/call-conv-field.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(not(test))] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct JNINativeInterface_ { - pub GetVersion: ::std::option::Option< - unsafe extern "stdcall" fn(env: *mut ::std::os::raw::c_void) - -> ::std::os::raw::c_int, - >, - pub __hack: ::std::os::raw::c_ulonglong, -} -#[test] -fn bindgen_test_layout_JNINativeInterface_() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).GetVersion as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(GetVersion) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__hack as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(__hack) - ) - ); -} -impl Default for JNINativeInterface_ { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_bar@0"] - pub fn bar(); -} diff --git a/tests/expectations/tests/libclang-3.8/const_bool.rs b/tests/expectations/tests/libclang-3.8/const_bool.rs deleted file mode 100644 index 356368426b..0000000000 --- a/tests/expectations/tests/libclang-3.8/const_bool.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_ZL1k"] - pub static mut k: bool; -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN1A1kE"] - pub static mut A_k: bool; -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} -pub type foo = bool; -extern "C" { - #[link_name = "\u{1}_ZL2k2"] - pub static mut k2: foo; -} diff --git a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs b/tests/expectations/tests/libclang-3.8/constant-evaluate.rs deleted file mode 100644 index 8faddfe969..0000000000 --- a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; -pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { foo = 4, bar = 8, } -pub type EasyToOverflow = ::std::os::raw::c_ulonglong; -pub const k: EasyToOverflow = 2147483648; -extern "C" { - #[link_name = "\u{1}k_expr"] - pub static mut k_expr: EasyToOverflow; -} -extern "C" { - #[link_name = "\u{1}BAZ"] - pub static mut BAZ: ::std::os::raw::c_longlong; -} -extern "C" { - #[link_name = "\u{1}fuzz"] - pub static mut fuzz: f64; -} -extern "C" { - #[link_name = "\u{1}BAZZ"] - pub static mut BAZZ: ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}WAT"] - pub static mut WAT: ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}bytestring"] - pub static mut bytestring: *const ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}NOT_UTF8"] - pub static mut NOT_UTF8: *const ::std::os::raw::c_char; -} diff --git a/tests/expectations/tests/libclang-3.8/issue-769-bad-instantiation-test.rs b/tests/expectations/tests/libclang-3.8/issue-769-bad-instantiation-test.rs deleted file mode 100644 index 0603873df2..0000000000 --- a/tests/expectations/tests/libclang-3.8/issue-769-bad-instantiation-test.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Rooted { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation_1() { - assert_eq ! ( :: std :: mem :: size_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } -} diff --git a/tests/expectations/tests/libclang-3.8/objc_template.rs b/tests/expectations/tests/libclang-3.8/objc_template.rs deleted file mode 100644 index c5d16ae13a..0000000000 --- a/tests/expectations/tests/libclang-3.8/objc_template.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> id; -} -impl Foo for id { - unsafe fn get(self) -> id { - msg_send!(self, get) - } -} diff --git a/tests/expectations/tests/libclang-3.8/partial-specialization-and-inheritance.rs b/tests/expectations/tests/libclang-3.8/partial-specialization-and-inheritance.rs deleted file mode 100644 index 797d5f45ed..0000000000 --- a/tests/expectations/tests/libclang-3.8/partial-specialization-and-inheritance.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Base { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Derived { - pub b: bool, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Usage { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN5Usage13static_memberE"] - pub static mut Usage_static_member: [u32; 2usize]; -} -#[test] -fn bindgen_test_layout_Usage() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Usage)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Usage)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN5UsageC1Ev"] - pub fn Usage_Usage(this: *mut Usage); -} -impl Usage { - #[inline] - pub unsafe fn new() -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - Usage_Usage(&mut __bindgen_tmp); - __bindgen_tmp - } -} diff --git a/tests/expectations/tests/libclang-3.8/type_alias_template_specialized.rs b/tests/expectations/tests/libclang-3.8/type_alias_template_specialized.rs deleted file mode 100644 index a0d9ade6d0..0000000000 --- a/tests/expectations/tests/libclang-3.8/type_alias_template_specialized.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Rooted { - pub ptr: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Rooted() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Rooted)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Rooted)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Rooted), - "::", - stringify!(ptr) - ) - ); -} -///
-pub type MaybeWrapped
= a; diff --git a/tests/expectations/tests/libclang-3.9/auto.rs b/tests/expectations/tests/libclang-3.9/auto.rs deleted file mode 100644 index 2d7dfa3a85..0000000000 --- a/tests/expectations/tests/libclang-3.9/auto.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_kFoo: bool = true; -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_Z5Test2v"] - pub fn Test2() -> ::std::os::raw::c_uint; -} diff --git a/tests/expectations/tests/libclang-3.9/call-conv-field.rs b/tests/expectations/tests/libclang-3.9/call-conv-field.rs deleted file mode 100644 index 375eb9ad83..0000000000 --- a/tests/expectations/tests/libclang-3.9/call-conv-field.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(not(test))] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct JNINativeInterface_ { - pub GetVersion: ::std::option::Option< - unsafe extern "stdcall" fn(env: *mut ::std::os::raw::c_void) - -> ::std::os::raw::c_int, - >, - pub __hack: ::std::os::raw::c_ulonglong, -} -#[test] -fn bindgen_test_layout_JNINativeInterface_() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).GetVersion as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(GetVersion) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__hack as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(__hack) - ) - ); -} -impl Default for JNINativeInterface_ { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "stdcall" { - #[link_name = "\u{1}_bar@0"] - pub fn bar(); -} diff --git a/tests/expectations/tests/libclang-3.9/const_bool.rs b/tests/expectations/tests/libclang-3.9/const_bool.rs deleted file mode 100644 index 14f5139400..0000000000 --- a/tests/expectations/tests/libclang-3.9/const_bool.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const k: bool = true; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub _address: u8, -} -pub const A_k: bool = false; -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} -pub type foo = bool; -pub const k2: foo = true; diff --git a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs b/tests/expectations/tests/libclang-3.9/constant-evaluate.rs deleted file mode 100644 index 159dba7c52..0000000000 --- a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; -pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - foo = 4, - bar = 8, -} -pub type EasyToOverflow = ::std::os::raw::c_ulonglong; -pub const k: EasyToOverflow = 2147483648; -pub const k_expr: EasyToOverflow = 0; -pub const BAZ: ::std::os::raw::c_longlong = 24; -pub const fuzz: f64 = 51.0; -pub const BAZZ: ::std::os::raw::c_char = 53; -pub const WAT: ::std::os::raw::c_char = 0; -pub const bytestring: &'static [u8; 4usize] = b"Foo\0"; -pub const NOT_UTF8: [u8; 5usize] = [240u8, 40u8, 140u8, 40u8, 0u8]; diff --git a/tests/expectations/tests/libclang-3.9/issue-769-bad-instantiation-test.rs b/tests/expectations/tests/libclang-3.9/issue-769-bad-instantiation-test.rs deleted file mode 100644 index 0603873df2..0000000000 --- a/tests/expectations/tests/libclang-3.9/issue-769-bad-instantiation-test.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Rooted { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation_1() { - assert_eq ! ( :: std :: mem :: size_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } -} diff --git a/tests/expectations/tests/libclang-3.9/objc_template.rs b/tests/expectations/tests/libclang-3.9/objc_template.rs deleted file mode 100644 index c5d16ae13a..0000000000 --- a/tests/expectations/tests/libclang-3.9/objc_template.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> id; -} -impl Foo for id { - unsafe fn get(self) -> id { - msg_send!(self, get) - } -} diff --git a/tests/expectations/tests/libclang-3.9/partial-specialization-and-inheritance.rs b/tests/expectations/tests/libclang-3.9/partial-specialization-and-inheritance.rs deleted file mode 100644 index 97d2eabe41..0000000000 --- a/tests/expectations/tests/libclang-3.9/partial-specialization-and-inheritance.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Base { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Derived { - pub b: bool, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Usage { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN5Usage13static_memberE"] - pub static mut Usage_static_member: [u32; 2usize]; -} -#[test] -fn bindgen_test_layout_Usage() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Usage)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Usage)) - ); -} diff --git a/tests/expectations/tests/libclang-3.9/type_alias_template_specialized.rs b/tests/expectations/tests/libclang-3.9/type_alias_template_specialized.rs deleted file mode 100644 index a0d9ade6d0..0000000000 --- a/tests/expectations/tests/libclang-3.9/type_alias_template_specialized.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Rooted { - pub ptr: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Rooted() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Rooted)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Rooted)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Rooted), - "::", - stringify!(ptr) - ) - ); -} -///
-pub type MaybeWrapped
= a; diff --git a/tests/expectations/tests/libclang-4/auto.rs b/tests/expectations/tests/libclang-4/auto.rs deleted file mode 100644 index 2d7dfa3a85..0000000000 --- a/tests/expectations/tests/libclang-4/auto.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_kFoo: bool = true; -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_Z5Test2v"] - pub fn Test2() -> ::std::os::raw::c_uint; -} diff --git a/tests/expectations/tests/libclang-4/call-conv-field.rs b/tests/expectations/tests/libclang-4/call-conv-field.rs deleted file mode 100644 index 375eb9ad83..0000000000 --- a/tests/expectations/tests/libclang-4/call-conv-field.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(not(test))] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct JNINativeInterface_ { - pub GetVersion: ::std::option::Option< - unsafe extern "stdcall" fn(env: *mut ::std::os::raw::c_void) - -> ::std::os::raw::c_int, - >, - pub __hack: ::std::os::raw::c_ulonglong, -} -#[test] -fn bindgen_test_layout_JNINativeInterface_() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).GetVersion as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(GetVersion) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__hack as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(__hack) - ) - ); -} -impl Default for JNINativeInterface_ { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "stdcall" { - #[link_name = "\u{1}_bar@0"] - pub fn bar(); -} diff --git a/tests/expectations/tests/libclang-4/const_bool.rs b/tests/expectations/tests/libclang-4/const_bool.rs deleted file mode 100644 index 14f5139400..0000000000 --- a/tests/expectations/tests/libclang-4/const_bool.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const k: bool = true; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub _address: u8, -} -pub const A_k: bool = false; -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} -pub type foo = bool; -pub const k2: foo = true; diff --git a/tests/expectations/tests/libclang-4/constant-evaluate.rs b/tests/expectations/tests/libclang-4/constant-evaluate.rs deleted file mode 100644 index 045710f9d7..0000000000 --- a/tests/expectations/tests/libclang-4/constant-evaluate.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; -pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - foo = 4, - bar = 8, -} -pub type EasyToOverflow = ::std::os::raw::c_ulonglong; -pub const k: EasyToOverflow = 2147483648; -pub const k_expr: EasyToOverflow = 0; -pub const BAZ: ::std::os::raw::c_longlong = 24; -pub const fuzz: f64 = 51.0; -pub const BAZZ: ::std::os::raw::c_char = 53; -pub const WAT: ::std::os::raw::c_char = 0; -pub const bytestring: &'static [u8; 4usize] = b"Foo\0"; -pub const NOT_UTF8: [u8; 5usize] = [240u8, 40u8, 140u8, 40u8, 0u8]; diff --git a/tests/expectations/tests/libclang-4/issue-769-bad-instantiation-test.rs b/tests/expectations/tests/libclang-4/issue-769-bad-instantiation-test.rs deleted file mode 100644 index 86fad78d46..0000000000 --- a/tests/expectations/tests/libclang-4/issue-769-bad-instantiation-test.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Rooted { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - pub type AutoValueVector_Alias = ::std::os::raw::c_int; - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } - #[test] - fn __bindgen_test_layout_Rooted_open0_AutoValueVector_Alias_close0_instantiation() { - assert_eq ! ( :: std :: mem :: size_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); - } -} diff --git a/tests/expectations/tests/libclang-4/objc_template.rs b/tests/expectations/tests/libclang-4/objc_template.rs deleted file mode 100644 index 06a9a55f40..0000000000 --- a/tests/expectations/tests/libclang-4/objc_template.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#![cfg(target_os="macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) - -> *mut ObjectType; -} -impl Foo for id { - unsafe fn get(self) -> *mut ObjectType { msg_send!(self , get) } -} diff --git a/tests/expectations/tests/libclang-4/partial-specialization-and-inheritance.rs b/tests/expectations/tests/libclang-4/partial-specialization-and-inheritance.rs deleted file mode 100644 index 97d2eabe41..0000000000 --- a/tests/expectations/tests/libclang-4/partial-specialization-and-inheritance.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Base { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Derived { - pub b: bool, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Usage { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN5Usage13static_memberE"] - pub static mut Usage_static_member: [u32; 2usize]; -} -#[test] -fn bindgen_test_layout_Usage() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Usage)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Usage)) - ); -} diff --git a/tests/expectations/tests/libclang-4/type_alias_template_specialized.rs b/tests/expectations/tests/libclang-4/type_alias_template_specialized.rs deleted file mode 100644 index a09323a8f2..0000000000 --- a/tests/expectations/tests/libclang-4/type_alias_template_specialized.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: MaybeWrapped<::std::os::raw::c_int>, -} -#[test] -fn bindgen_test_layout_Rooted() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Rooted)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Rooted)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Rooted), - "::", - stringify!(ptr) - ) - ); -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -///
-pub type MaybeWrapped
= a; -#[test] -fn __bindgen_test_layout_MaybeWrapped_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(MaybeWrapped<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(MaybeWrapped<::std::os::raw::c_int>) - ) - ); -} diff --git a/tests/expectations/tests/libclang-5/auto.rs b/tests/expectations/tests/libclang-5/auto.rs deleted file mode 100644 index 2d7dfa3a85..0000000000 --- a/tests/expectations/tests/libclang-5/auto.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_kFoo: bool = true; -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_Z5Test2v"] - pub fn Test2() -> ::std::os::raw::c_uint; -} diff --git a/tests/expectations/tests/libclang-5/call-conv-field.rs b/tests/expectations/tests/libclang-5/call-conv-field.rs deleted file mode 100644 index 295a23f9ac..0000000000 --- a/tests/expectations/tests/libclang-5/call-conv-field.rs +++ /dev/null @@ -1,51 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(not(test))] - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct JNINativeInterface_ { - pub GetVersion: ::std::option::Option< - unsafe extern "stdcall" fn(env: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, - >, - pub __bindgen_padding_0: u32, - pub __hack: ::std::os::raw::c_ulonglong, -} -#[test] -fn bindgen_test_layout_JNINativeInterface_() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(JNINativeInterface_)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).GetVersion as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(GetVersion) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__hack as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(JNINativeInterface_), - "::", - stringify!(__hack) - ) - ); -} -impl Default for JNINativeInterface_ { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "stdcall" { - #[link_name = "\u{1}_bar@0"] - pub fn bar(); -} diff --git a/tests/expectations/tests/libclang-5/const_bool.rs b/tests/expectations/tests/libclang-5/const_bool.rs deleted file mode 100644 index 14f5139400..0000000000 --- a/tests/expectations/tests/libclang-5/const_bool.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const k: bool = true; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub _address: u8, -} -pub const A_k: bool = false; -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(A)) - ); -} -pub type foo = bool; -pub const k2: foo = true; diff --git a/tests/expectations/tests/libclang-5/constant-evaluate.rs b/tests/expectations/tests/libclang-5/constant-evaluate.rs deleted file mode 100644 index 045710f9d7..0000000000 --- a/tests/expectations/tests/libclang-5/constant-evaluate.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; -pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { - foo = 4, - bar = 8, -} -pub type EasyToOverflow = ::std::os::raw::c_ulonglong; -pub const k: EasyToOverflow = 2147483648; -pub const k_expr: EasyToOverflow = 0; -pub const BAZ: ::std::os::raw::c_longlong = 24; -pub const fuzz: f64 = 51.0; -pub const BAZZ: ::std::os::raw::c_char = 53; -pub const WAT: ::std::os::raw::c_char = 0; -pub const bytestring: &'static [u8; 4usize] = b"Foo\0"; -pub const NOT_UTF8: [u8; 5usize] = [240u8, 40u8, 140u8, 40u8, 0u8]; diff --git a/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs b/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs deleted file mode 100644 index 86fad78d46..0000000000 --- a/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Rooted { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - pub type AutoValueVector_Alias = ::std::os::raw::c_int; - #[test] - fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); - } - #[test] - fn __bindgen_test_layout_Rooted_open0_AutoValueVector_Alias_close0_instantiation() { - assert_eq ! ( :: std :: mem :: size_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); - assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); - } -} diff --git a/tests/expectations/tests/libclang-5/objc_template.rs b/tests/expectations/tests/libclang-5/objc_template.rs deleted file mode 100644 index 06a9a55f40..0000000000 --- a/tests/expectations/tests/libclang-5/objc_template.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#![cfg(target_os="macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) - -> *mut ObjectType; -} -impl Foo for id { - unsafe fn get(self) -> *mut ObjectType { msg_send!(self , get) } -} diff --git a/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs b/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs deleted file mode 100644 index 97d2eabe41..0000000000 --- a/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Base { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Derived { - pub b: bool, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Usage { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN5Usage13static_memberE"] - pub static mut Usage_static_member: [u32; 2usize]; -} -#[test] -fn bindgen_test_layout_Usage() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Usage)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Usage)) - ); -} diff --git a/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs b/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs deleted file mode 100644 index a09323a8f2..0000000000 --- a/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: MaybeWrapped<::std::os::raw::c_int>, -} -#[test] -fn bindgen_test_layout_Rooted() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Rooted)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Rooted)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ptr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Rooted), - "::", - stringify!(ptr) - ) - ); -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -///
-pub type MaybeWrapped
= a; -#[test] -fn __bindgen_test_layout_MaybeWrapped_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(MaybeWrapped<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(MaybeWrapped<::std::os::raw::c_int>) - ) - ); -} diff --git a/tests/expectations/tests/libclang_version_specific_generated_tests.rs b/tests/expectations/tests/libclang_version_specific_generated_tests.rs deleted file mode 100644 index 93cf0d47cc..0000000000 --- a/tests/expectations/tests/libclang_version_specific_generated_tests.rs +++ /dev/null @@ -1 +0,0 @@ -include!(concat!(env!("OUT_DIR"), "/libclang_version_specific_generated_tests.rs")); diff --git a/tests/expectations/tests/macro-expr-uncommon-token.rs b/tests/expectations/tests/macro-expr-uncommon-token.rs deleted file mode 100644 index 95093ad635..0000000000 --- a/tests/expectations/tests/macro-expr-uncommon-token.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const MODBUS_WOOT: u32 = 3; -extern "C" { - pub fn foo(); -} diff --git a/tests/expectations/tests/macro_const.rs b/tests/expectations/tests/macro_const.rs deleted file mode 100644 index 382af9a5ef..0000000000 --- a/tests/expectations/tests/macro_const.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const foo: &'static [u8; 4usize] = b"bar\0"; -pub const CHAR: u8 = 98u8; -pub const CHARR: u8 = 0u8; -pub const FLOAT: f64 = 5.09; -pub const FLOAT_EXPR: f64 = 0.005; -pub const INVALID_UTF8: [u8; 5usize] = [240u8, 40u8, 140u8, 40u8, 0u8]; diff --git a/tests/expectations/tests/mangling-ios.rs b/tests/expectations/tests/mangling-ios.rs deleted file mode 100644 index 0fddb5d707..0000000000 --- a/tests/expectations/tests/mangling-ios.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_foo"] - pub fn foo(); -} diff --git a/tests/expectations/tests/mangling-linux32.rs b/tests/expectations/tests/mangling-linux32.rs deleted file mode 100644 index 7fe8f33a7f..0000000000 --- a/tests/expectations/tests/mangling-linux32.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4sBarE"] - pub static mut Foo_sBar: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/mangling-linux64.rs b/tests/expectations/tests/mangling-linux64.rs deleted file mode 100644 index 7fe8f33a7f..0000000000 --- a/tests/expectations/tests/mangling-linux64.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4sBarE"] - pub static mut Foo_sBar: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/mangling-macos.rs b/tests/expectations/tests/mangling-macos.rs deleted file mode 100644 index 7835dd928c..0000000000 --- a/tests/expectations/tests/mangling-macos.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_foo"] - pub fn foo(); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}__ZN3Foo4sBarE"] - pub static mut Foo_sBar: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/mangling-win32.rs b/tests/expectations/tests/mangling-win32.rs deleted file mode 100644 index 2d2d7fcdbd..0000000000 --- a/tests/expectations/tests/mangling-win32.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_foo"] - pub fn foo(); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}?sBar@Foo@@2_NA"] - pub static mut Foo_sBar: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/mangling-win64.rs b/tests/expectations/tests/mangling-win64.rs deleted file mode 100644 index 0d9c49faf7..0000000000 --- a/tests/expectations/tests/mangling-win64.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}?sBar@Foo@@2_NA"] - pub static mut Foo_sBar: bool; -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} diff --git a/tests/expectations/tests/method-mangling.rs b/tests/expectations/tests/method-mangling.rs deleted file mode 100644 index f2eb6f9802..0000000000 --- a/tests/expectations/tests/method-mangling.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3Foo4typeEv"] - pub fn Foo_type(this: *mut Foo) -> ::std::os::raw::c_int; -} -impl Foo { - #[inline] - pub unsafe fn type_(&mut self) -> ::std::os::raw::c_int { - Foo_type(self) - } -} diff --git a/tests/expectations/tests/module-whitelisted.rs b/tests/expectations/tests/module-whitelisted.rs deleted file mode 100644 index 3f2d304e82..0000000000 --- a/tests/expectations/tests/module-whitelisted.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Test { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Test)) - ); - } -} diff --git a/tests/expectations/tests/msvc-no-usr.rs b/tests/expectations/tests/msvc-no-usr.rs deleted file mode 100644 index 94d5a671a2..0000000000 --- a/tests/expectations/tests/msvc-no-usr.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub foo: usize, -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(foo)) - ); -} diff --git a/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs b/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs deleted file mode 100644 index 86147bdd10..0000000000 --- a/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bar)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Baz { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Baz)) - ); -} diff --git a/tests/expectations/tests/mutable.rs b/tests/expectations/tests/mutable.rs deleted file mode 100644 index d60e6cf790..0000000000 --- a/tests/expectations/tests/mutable.rs +++ /dev/null @@ -1,110 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct C { - pub m_member: ::std::os::raw::c_int, - pub m_other: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(m_member) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_other as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(m_other) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct NonCopiable { - pub m_member: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NonCopiable() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NonCopiable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NonCopiable)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NonCopiable), - "::", - stringify!(m_member) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct NonCopiableWithNonCopiableMutableMember { - pub m_member: NonCopiable, -} -#[test] -fn bindgen_test_layout_NonCopiableWithNonCopiableMutableMember() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(NonCopiableWithNonCopiableMutableMember) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(NonCopiableWithNonCopiableMutableMember) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).m_member as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NonCopiableWithNonCopiableMutableMember), - "::", - stringify!(m_member) - ) - ); -} diff --git a/tests/expectations/tests/namespace.rs b/tests/expectations/tests/namespace.rs deleted file mode 100644 index 726383d05c..0000000000 --- a/tests/expectations/tests/namespace.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - extern "C" { - #[link_name = "\u{1}_Z9top_levelv"] - pub fn top_level(); - } - pub mod whatever { - #[allow(unused_imports)] - use self::super::super::root; - pub type whatever_int_t = ::std::os::raw::c_int; - extern "C" { - #[link_name = "\u{1}_ZN8whatever11in_whateverEv"] - pub fn in_whatever(); - } - } - pub mod _bindgen_mod_id_13 { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct A { - pub b: root::whatever::whatever_int_t, - } - #[test] - fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(b)) - ); - } - } - #[repr(C)] - #[derive(Debug)] - pub struct C { - pub _base: root::_bindgen_mod_id_13::A, - pub m_c: T, - pub m_c_ptr: *mut T, - pub m_c_arr: [T; 10usize], - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - pub mod w { - #[allow(unused_imports)] - use self::super::super::root; - pub type whatever_int_t = ::std::os::raw::c_uint; - #[repr(C)] - #[derive(Debug)] - pub struct D { - pub m_c: root::C, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for D { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - extern "C" { - #[link_name = "\u{1}_ZN1w3hehEv"] - pub fn heh() -> root::w::whatever_int_t; - } - extern "C" { - #[link_name = "\u{1}_ZN1w3fooEv"] - pub fn foo() -> root::C<::std::os::raw::c_int>; - } - extern "C" { - #[link_name = "\u{1}_ZN1w4barrEv"] - pub fn barr() -> root::C; - } - } -} diff --git a/tests/expectations/tests/nested.rs b/tests/expectations/tests/nested.rs deleted file mode 100644 index 4022909ccd..0000000000 --- a/tests/expectations/tests/nested.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Calc { - pub w: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Calc() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Calc)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Calc)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).w as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Calc), "::", stringify!(w)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Test { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Test_Size { - pub mWidth: Test_Size_Dimension, - pub mHeight: Test_Size_Dimension, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Test_Size_Dimension { - pub _base: Calc, -} -#[test] -fn bindgen_test_layout_Test_Size_Dimension() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Test_Size_Dimension)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Test_Size_Dimension)) - ); -} -#[test] -fn bindgen_test_layout_Test_Size() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Test_Size)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Test_Size)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mWidth as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Test_Size), - "::", - stringify!(mWidth) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mHeight as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(Test_Size), - "::", - stringify!(mHeight) - ) - ); -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Test)) - ); -} diff --git a/tests/expectations/tests/nested_vtable.rs b/tests/expectations/tests/nested_vtable.rs deleted file mode 100644 index 4082610644..0000000000 --- a/tests/expectations/tests/nested_vtable.rs +++ /dev/null @@ -1,81 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct nsISupports__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsISupports { - pub vtable_: *const nsISupports__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsISupports() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsISupports)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsISupports)) - ); -} -impl Default for nsISupports { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN11nsISupports14QueryInterfaceEv"] - pub fn nsISupports_QueryInterface(this: *mut ::std::os::raw::c_void) -> *mut nsISupports; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsIRunnable { - pub _base: nsISupports, -} -#[test] -fn bindgen_test_layout_nsIRunnable() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsIRunnable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsIRunnable)) - ); -} -impl Default for nsIRunnable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Runnable { - pub _base: nsIRunnable, -} -#[test] -fn bindgen_test_layout_Runnable() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Runnable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Runnable)) - ); -} -impl Default for Runnable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/nested_within_namespace.rs b/tests/expectations/tests/nested_within_namespace.rs deleted file mode 100644 index 868510e8a1..0000000000 --- a/tests/expectations/tests/nested_within_namespace.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod foo { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar { - pub foo: ::std::os::raw::c_int, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar_Baz { - pub foo: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_Bar_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar_Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar_Baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Bar_Baz), - "::", - stringify!(foo) - ) - ); - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(foo)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Baz { - pub baz: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Baz)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Baz), "::", stringify!(baz)) - ); - } - } -} diff --git a/tests/expectations/tests/no-comments.rs b/tests/expectations/tests/no-comments.rs deleted file mode 100644 index 65f6962437..0000000000 --- a/tests/expectations/tests/no-comments.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub s: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(s)) - ); -} diff --git a/tests/expectations/tests/no-derive-debug.rs b/tests/expectations/tests/no-derive-debug.rs deleted file mode 100644 index 6272d7739b..0000000000 --- a/tests/expectations/tests/no-derive-debug.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Default)] -pub struct foo { - bar: ::std::os::raw::c_int, -} - - -/// bar should compile. It will normally derive debug, but our blacklist of foo -/// and replacement for another type that doesn't implement it would prevent it -/// from building if --no-derive-debug didn't work. -#[repr(C)] -pub struct bar { - pub foo: foo, - pub baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(baz)) - ); -} -impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/no-derive-default.rs b/tests/expectations/tests/no-derive-default.rs deleted file mode 100644 index da5e10015d..0000000000 --- a/tests/expectations/tests/no-derive-default.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct foo { - bar: ::std::os::raw::c_int, -} - - -/// bar should compile. It will normally derive default, but our blacklist of foo -/// and replacement for another type that doesn't implement it would prevent it -/// from building if --no-derive-default didn't work. -#[repr(C)] -pub struct bar { - pub foo: foo, - pub baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(baz)) - ); -} diff --git a/tests/expectations/tests/no-hash-opaque.rs b/tests/expectations/tests/no-hash-opaque.rs deleted file mode 100644 index c4211c71b1..0000000000 --- a/tests/expectations/tests/no-hash-opaque.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoHash { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_NoHash() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoHash)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoHash)) - ); -} diff --git a/tests/expectations/tests/no-hash-whitelisted.rs b/tests/expectations/tests/no-hash-whitelisted.rs deleted file mode 100644 index fd54300d29..0000000000 --- a/tests/expectations/tests/no-hash-whitelisted.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoHash { - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NoHash() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoHash)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoHash)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(NoHash), "::", stringify!(i)) - ); -} diff --git a/tests/expectations/tests/no-partialeq-opaque.rs b/tests/expectations/tests/no-partialeq-opaque.rs deleted file mode 100644 index 1a7941623d..0000000000 --- a/tests/expectations/tests/no-partialeq-opaque.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoPartialEq { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_NoPartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoPartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoPartialEq)) - ); -} diff --git a/tests/expectations/tests/no-partialeq-whitelisted.rs b/tests/expectations/tests/no-partialeq-whitelisted.rs deleted file mode 100644 index 00f7210e8e..0000000000 --- a/tests/expectations/tests/no-partialeq-whitelisted.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoPartialEq { - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NoPartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoPartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoPartialEq)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NoPartialEq), - "::", - stringify!(i) - ) - ); -} diff --git a/tests/expectations/tests/no-recursive-whitelisting.rs b/tests/expectations/tests/no-recursive-whitelisting.rs deleted file mode 100644 index e8fb69447a..0000000000 --- a/tests/expectations/tests/no-recursive-whitelisting.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub enum Bar {} - -#[repr(C)] -pub struct Foo { - pub baz: *mut Bar, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(baz)) - ); -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/no-std.rs b/tests/expectations/tests/no-std.rs deleted file mode 100644 index 524b307a57..0000000000 --- a/tests/expectations/tests/no-std.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![no_std] -mod libc { - pub type c_int = i32; - pub enum c_void {} -} - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct foo { - pub a: libc::c_int, - pub b: libc::c_int, - pub bar: *mut libc::c_void, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::core::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::core::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).bar as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/no_copy_opaque.rs b/tests/expectations/tests/no_copy_opaque.rs deleted file mode 100644 index 8de90cd4ec..0000000000 --- a/tests/expectations/tests/no_copy_opaque.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct NoCopy { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_NoCopy() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoCopy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoCopy)) - ); -} diff --git a/tests/expectations/tests/no_copy_whitelisted.rs b/tests/expectations/tests/no_copy_whitelisted.rs deleted file mode 100644 index 340fc1ece6..0000000000 --- a/tests/expectations/tests/no_copy_whitelisted.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct NoCopy { - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NoCopy() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(NoCopy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(NoCopy)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(NoCopy), "::", stringify!(i)) - ); -} diff --git a/tests/expectations/tests/non-type-params.rs b/tests/expectations/tests/non-type-params.rs deleted file mode 100644 index 4ba6425748..0000000000 --- a/tests/expectations/tests/non-type-params.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type Array16 = u8; -pub type ArrayInt4 = [u32; 4usize]; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct UsesArray { - pub array_char_16: [u8; 16usize], - pub array_bool_8: [u8; 8usize], - pub array_int_4: ArrayInt4, -} -#[test] -fn bindgen_test_layout_UsesArray() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(UsesArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(UsesArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).array_char_16 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(UsesArray), - "::", - stringify!(array_char_16) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).array_bool_8 as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(UsesArray), - "::", - stringify!(array_bool_8) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).array_int_4 as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(UsesArray), - "::", - stringify!(array_int_4) - ) - ); -} diff --git a/tests/expectations/tests/nsBaseHashtable.rs b/tests/expectations/tests/nsBaseHashtable.rs deleted file mode 100644 index 338978e1c8..0000000000 --- a/tests/expectations/tests/nsBaseHashtable.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct nsBaseHashtableET { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct nsTHashtable { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsBaseHashtable { - pub _address: u8, -} -pub type nsBaseHashtable_KeyType = [u8; 0usize]; -pub type nsBaseHashtable_EntryType = nsBaseHashtableET; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsBaseHashtable_LookupResult { - pub mEntry: *mut nsBaseHashtable_EntryType, - pub mTable: *mut nsBaseHashtable, -} -impl Default for nsBaseHashtable_LookupResult { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug)] -pub struct nsBaseHashtable_EntryPtr { - pub mEntry: *mut nsBaseHashtable_EntryType, - pub mExistingEntry: bool, -} -impl Default for nsBaseHashtable_EntryPtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for nsBaseHashtable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/nsStyleAutoArray.rs b/tests/expectations/tests/nsStyleAutoArray.rs deleted file mode 100644 index bd5e7f4b83..0000000000 --- a/tests/expectations/tests/nsStyleAutoArray.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsTArray { - pub mBuff: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for nsTArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsStyleAutoArray { - pub mFirstElement: T, - pub mOtherElements: nsTArray, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum nsStyleAutoArray_WithSingleInitialElement { - WITH_SINGLE_INITIAL_ELEMENT = 0, -} -impl Default for nsStyleAutoArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/objc_category.rs b/tests/expectations/tests/objc_category.rs deleted file mode 100644 index ba37b819cf..0000000000 --- a/tests/expectations/tests/objc_category.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(self); -} -impl Foo for id { - unsafe fn method(self) { - msg_send!(self, method) - } -} -pub trait Foo_BarCategory { - unsafe fn categoryMethod(self); -} -impl Foo_BarCategory for id { - unsafe fn categoryMethod(self) { - msg_send!(self, categoryMethod) - } -} diff --git a/tests/expectations/tests/objc_class.rs b/tests/expectations/tests/objc_class.rs deleted file mode 100644 index b5c15a0e2a..0000000000 --- a/tests/expectations/tests/objc_class.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -extern "C" { - #[link_name = "\u{1}fooVar"] - pub static mut fooVar: *mut id; -} -pub trait Foo { - unsafe fn method(self); -} -impl Foo for id { - unsafe fn method(self) { - msg_send!(self, method) - } -} diff --git a/tests/expectations/tests/objc_class_method.rs b/tests/expectations/tests/objc_class_method.rs deleted file mode 100644 index 2c5a326d80..0000000000 --- a/tests/expectations/tests/objc_class_method.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(); - unsafe fn methodWithInt_(foo: ::std::os::raw::c_int); - unsafe fn methodWithFoo_(foo: id); - unsafe fn methodReturningInt() -> ::std::os::raw::c_int; - unsafe fn methodReturningFoo() -> *mut id; - unsafe fn methodWithArg1_andArg2_andArg3_( - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ); -} -impl Foo for id { - unsafe fn method() { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - method - ) - } - unsafe fn methodWithInt_(foo: ::std::os::raw::c_int) { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - methodWithInt: foo - ) - } - unsafe fn methodWithFoo_(foo: id) { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - methodWithFoo: foo - ) - } - unsafe fn methodReturningInt() -> ::std::os::raw::c_int { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - methodReturningInt - ) - } - unsafe fn methodReturningFoo() -> *mut id { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - methodReturningFoo - ) - } - unsafe fn methodWithArg1_andArg2_andArg3_( - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ) { - msg_send ! ( objc :: runtime :: Class :: get ( "Foo" ) . expect ( "Couldn\'t find Foo" ) , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) - } -} diff --git a/tests/expectations/tests/objc_interface.rs b/tests/expectations/tests/objc_interface.rs deleted file mode 100644 index e8c1278ac2..0000000000 --- a/tests/expectations/tests/objc_interface.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo {} -impl Foo for id {} -pub trait protocol_bar {} -impl protocol_bar for id {} diff --git a/tests/expectations/tests/objc_interface_type.rs b/tests/expectations/tests/objc_interface_type.rs deleted file mode 100644 index 9931f5a94c..0000000000 --- a/tests/expectations/tests/objc_interface_type.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo {} -impl Foo for id {} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct FooStruct { - pub foo: *mut id, -} -#[test] -fn bindgen_test_layout_FooStruct() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(FooStruct)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(FooStruct)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(FooStruct), - "::", - stringify!(foo) - ) - ); -} -impl Default for FooStruct { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - pub fn fooFunc(foo: id); -} -extern "C" { - #[link_name = "\u{1}kFoo"] - pub static mut kFoo: *const id; -} diff --git a/tests/expectations/tests/objc_method.rs b/tests/expectations/tests/objc_method.rs deleted file mode 100644 index bd6e748a91..0000000000 --- a/tests/expectations/tests/objc_method.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(self); - unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int); - unsafe fn methodWithFoo_(self, foo: id); - unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int; - unsafe fn methodReturningFoo(self) -> *mut id; - unsafe fn methodWithArg1_andArg2_andArg3_( - self, - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ); -} -impl Foo for id { - unsafe fn method(self) { - msg_send!(self, method) - } - unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int) { - msg_send!(self, methodWithInt: foo) - } - unsafe fn methodWithFoo_(self, foo: id) { - msg_send!(self, methodWithFoo: foo) - } - unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int { - msg_send!(self, methodReturningInt) - } - unsafe fn methodReturningFoo(self) -> *mut id { - msg_send!(self, methodReturningFoo) - } - unsafe fn methodWithArg1_andArg2_andArg3_( - self, - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ) { - msg_send ! ( self , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) - } -} diff --git a/tests/expectations/tests/objc_method_clash.rs b/tests/expectations/tests/objc_method_clash.rs deleted file mode 100644 index 158a044391..0000000000 --- a/tests/expectations/tests/objc_method_clash.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn foo(self); - unsafe fn class_foo(); -} -impl Foo for id { - unsafe fn foo(self) { - msg_send!(self, foo) - } - unsafe fn class_foo() { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn\'t find Foo"), - foo - ) - } -} diff --git a/tests/expectations/tests/objc_property_fnptr.rs b/tests/expectations/tests/objc_property_fnptr.rs deleted file mode 100644 index 4f98f9fb0b..0000000000 --- a/tests/expectations/tests/objc_property_fnptr.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn func(self) -> ::std::option::Option ::std::os::raw::c_int>; - unsafe fn setFunc_( - self, - func: ::std::option::Option ::std::os::raw::c_int>, - ); -} -impl Foo for id { - unsafe fn func(self) -> ::std::option::Option ::std::os::raw::c_int> { - msg_send!(self, func) - } - unsafe fn setFunc_( - self, - func: ::std::option::Option ::std::os::raw::c_int>, - ) { - msg_send!(self, setFunc: func) - } -} diff --git a/tests/expectations/tests/objc_protocol.rs b/tests/expectations/tests/objc_protocol.rs deleted file mode 100644 index 33a81fa44c..0000000000 --- a/tests/expectations/tests/objc_protocol.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait protocol_Foo {} -impl protocol_Foo for id {} -pub trait Foo {} -impl Foo for id {} diff --git a/tests/expectations/tests/objc_sel_and_id.rs b/tests/expectations/tests/objc_sel_and_id.rs deleted file mode 100644 index 8802c206ea..0000000000 --- a/tests/expectations/tests/objc_sel_and_id.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -extern "C" { - #[link_name = "\u{1}object"] - pub static mut object: id; -} -extern "C" { - #[link_name = "\u{1}selector"] - pub static mut selector: objc::runtime::Sel; -} -extern "C" { - pub fn f(object: id, selector: objc::runtime::Sel); -} diff --git a/tests/expectations/tests/objc_whitelist.rs b/tests/expectations/tests/objc_whitelist.rs deleted file mode 100644 index 7a6e20fc20..0000000000 --- a/tests/expectations/tests/objc_whitelist.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(target_os = "macos")] - -#[macro_use] -extern crate objc; -#[allow(non_camel_case_types)] -pub type id = *mut objc::runtime::Object; -pub trait protocol_SomeProtocol { - unsafe fn protocolMethod(self); - unsafe fn protocolClassMethod(); -} -impl protocol_SomeProtocol for id { - unsafe fn protocolMethod(self) { - msg_send!(self, protocolMethod) - } - unsafe fn protocolClassMethod() { - msg_send!( - objc::runtime::Class::get("SomeProtocol").expect("Couldn\'t find SomeProtocol"), - protocolClassMethod - ) - } -} -pub trait WhitelistMe { - unsafe fn method(self); - unsafe fn classMethod(); -} -impl WhitelistMe for id { - unsafe fn method(self) { - msg_send!(self, method) - } - unsafe fn classMethod() { - msg_send!( - objc::runtime::Class::get("WhitelistMe").expect("Couldn\'t find WhitelistMe"), - classMethod - ) - } -} -pub trait WhitelistMe_InterestingCategory {} -impl WhitelistMe_InterestingCategory for id {} diff --git a/tests/expectations/tests/only_bitfields.rs b/tests/expectations/tests/only_bitfields.rs deleted file mode 100644 index 09bd8737ee..0000000000 --- a/tests/expectations/tests/only_bitfields.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone)] -pub struct C { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(C)) - ); -} -impl C { - #[inline] - pub fn a(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } - } - #[inline] - pub fn set_a(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) } - } - #[inline] - pub fn set_b(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 7u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(a: bool, b: bool) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let a: u8 = unsafe { ::std::mem::transmute(a) }; - a as u64 - }); - __bindgen_bitfield_unit.set(1usize, 7u8, { - let b: u8 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/opaque-template-inst-member-2.rs b/tests/expectations/tests/opaque-template-inst-member-2.rs deleted file mode 100644 index 99e507b86b..0000000000 --- a/tests/expectations/tests/opaque-template-inst-member-2.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// This is like `opaque-template-inst-member.hpp` except exercising the cases -/// where we are OK to derive Debug/Hash/PartialEq. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct OpaqueTemplate { - pub _address: u8, -} -/// Should derive Debug/Hash/PartialEq. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ContainsOpaqueTemplate { - pub mBlah: u32, - pub mBaz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContainsOpaqueTemplate() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ContainsOpaqueTemplate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContainsOpaqueTemplate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBlah as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueTemplate), - "::", - stringify!(mBlah) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBaz as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueTemplate), - "::", - stringify!(mBaz) - ) - ); -} -/// Should also derive Debug/Hash/PartialEq. -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct InheritsOpaqueTemplate { - pub _base: u8, - pub wow: *mut ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_InheritsOpaqueTemplate() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(InheritsOpaqueTemplate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(InheritsOpaqueTemplate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).wow as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(InheritsOpaqueTemplate), - "::", - stringify!(wow) - ) - ); -} -impl Default for InheritsOpaqueTemplate { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/opaque-template-inst-member.rs b/tests/expectations/tests/opaque-template-inst-member.rs deleted file mode 100644 index 6653123240..0000000000 --- a/tests/expectations/tests/opaque-template-inst-member.rs +++ /dev/null @@ -1,101 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct OpaqueTemplate { - pub _address: u8, -} -/// This should not end up deriving Debug/Hash because its `mBlah` field cannot derive -/// Debug/Hash because the instantiation's definition cannot derive Debug/Hash. -#[repr(C)] -pub struct ContainsOpaqueTemplate { - pub mBlah: [u32; 101usize], - pub mBaz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContainsOpaqueTemplate() { - assert_eq!( - ::std::mem::size_of::(), - 408usize, - concat!("Size of: ", stringify!(ContainsOpaqueTemplate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContainsOpaqueTemplate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBlah as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueTemplate), - "::", - stringify!(mBlah) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBaz as *const _ as usize }, - 404usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueTemplate), - "::", - stringify!(mBaz) - ) - ); -} -impl Default for ContainsOpaqueTemplate { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for ContainsOpaqueTemplate { - fn eq(&self, other: &ContainsOpaqueTemplate) -> bool { - &self.mBlah[..] == &other.mBlah[..] && self.mBaz == other.mBaz - } -} -/// This should not end up deriving Debug/Hash either, for similar reasons, although -/// we're exercising base member edges now. -#[repr(C)] -pub struct InheritsOpaqueTemplate { - pub _base: [u8; 401usize], - pub wow: *mut ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_InheritsOpaqueTemplate() { - assert_eq!( - ::std::mem::size_of::(), - 416usize, - concat!("Size of: ", stringify!(InheritsOpaqueTemplate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(InheritsOpaqueTemplate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).wow as *const _ as usize }, - 408usize, - concat!( - "Offset of field: ", - stringify!(InheritsOpaqueTemplate), - "::", - stringify!(wow) - ) - ); -} -impl Default for InheritsOpaqueTemplate { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl ::std::cmp::PartialEq for InheritsOpaqueTemplate { - fn eq(&self, other: &InheritsOpaqueTemplate) -> bool { - &self._base[..] == &other._base[..] && self.wow == other.wow - } -} diff --git a/tests/expectations/tests/opaque-template-instantiation-namespaced.rs b/tests/expectations/tests/opaque-template-instantiation-namespaced.rs deleted file mode 100644 index 4f5b0cb970..0000000000 --- a/tests/expectations/tests/opaque-template-instantiation-namespaced.rs +++ /dev/null @@ -1,158 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod zoidberg { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] - pub struct Template { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - } - impl Default for Template { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] - pub struct Foo { - pub c: ::std::os::raw::c_char, - } - #[test] - fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Foo), "::", stringify!(c)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] - pub struct Bar { - pub i: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).i as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(i)) - ); - } - #[repr(C)] - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] - pub struct ContainsInstantiation { - pub not_opaque: root::zoidberg::Template, - } - #[test] - fn bindgen_test_layout_ContainsInstantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ContainsInstantiation)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ContainsInstantiation)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).not_opaque as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsInstantiation), - "::", - stringify!(not_opaque) - ) - ); - } - impl Default for ContainsInstantiation { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] - pub struct ContainsOpaqueInstantiation { - pub opaque: u32, - } - #[test] - fn bindgen_test_layout_ContainsOpaqueInstantiation() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(ContainsOpaqueInstantiation)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContainsOpaqueInstantiation)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).opaque as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueInstantiation), - "::", - stringify!(opaque) - ) - ); - } - } - #[test] - fn __bindgen_test_layout_Template_open0_Foo_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 1usize, - concat!( - "Size of template specialization: ", - stringify!(root::zoidberg::Template) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(root::zoidberg::Template) - ) - ); - } -} diff --git a/tests/expectations/tests/opaque-template-instantiation.rs b/tests/expectations/tests/opaque-template-instantiation.rs deleted file mode 100644 index c3043abf19..0000000000 --- a/tests/expectations/tests/opaque-template-instantiation.rs +++ /dev/null @@ -1,101 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Template { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Template { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ContainsInstantiation { - pub not_opaque: Template<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_ContainsInstantiation() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(ContainsInstantiation)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ContainsInstantiation)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).not_opaque as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsInstantiation), - "::", - stringify!(not_opaque) - ) - ); -} -impl Default for ContainsInstantiation { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct ContainsOpaqueInstantiation { - pub opaque: u32, -} -#[test] -fn bindgen_test_layout_ContainsOpaqueInstantiation() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(ContainsOpaqueInstantiation)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContainsOpaqueInstantiation)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).opaque as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsOpaqueInstantiation), - "::", - stringify!(opaque) - ) - ); -} -#[test] -fn __bindgen_test_layout_Template_open0_char_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 1usize, - concat!( - "Size of template specialization: ", - stringify!(Template<::std::os::raw::c_char>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(Template<::std::os::raw::c_char>) - ) - ); -} diff --git a/tests/expectations/tests/opaque-tracing.rs b/tests/expectations/tests/opaque-tracing.rs deleted file mode 100644 index 87d91f3c4e..0000000000 --- a/tests/expectations/tests/opaque-tracing.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_Z3fooP9Container"] - pub fn foo(c: *mut Container); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Container { - pub _bindgen_opaque_blob: [u32; 2usize], -} -#[test] -fn bindgen_test_layout_Container() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Container)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Container)) - ); -} diff --git a/tests/expectations/tests/opaque_in_struct.rs b/tests/expectations/tests/opaque_in_struct.rs deleted file mode 100644 index 5984858101..0000000000 --- a/tests/expectations/tests/opaque_in_struct.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct opaque { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_opaque() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(opaque)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(opaque)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct container { - pub contained: opaque, -} -#[test] -fn bindgen_test_layout_container() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(container)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(container)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).contained as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(container), - "::", - stringify!(contained) - ) - ); -} diff --git a/tests/expectations/tests/opaque_pointer.rs b/tests/expectations/tests/opaque_pointer.rs deleted file mode 100644 index 736655a450..0000000000 --- a/tests/expectations/tests/opaque_pointer.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct OtherOpaque { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_OtherOpaque() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(OtherOpaque)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(OtherOpaque)) - ); -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Opaque { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq)] -pub struct WithOpaquePtr { - pub whatever: *mut u8, - pub other: u32, - pub t: OtherOpaque, -} -#[test] -fn bindgen_test_layout_WithOpaquePtr() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(WithOpaquePtr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(WithOpaquePtr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).whatever as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithOpaquePtr), - "::", - stringify!(whatever) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).other as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(WithOpaquePtr), - "::", - stringify!(other) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).t as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(WithOpaquePtr), - "::", - stringify!(t) - ) - ); -} -impl Default for WithOpaquePtr { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/overflowed_enum.rs b/tests/expectations/tests/overflowed_enum.rs deleted file mode 100644 index 25e9178601..0000000000 --- a/tests/expectations/tests/overflowed_enum.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { - BAP_ARM = 9698489, - BAP_X86 = 11960045, - BAP_X86_64 = 3128633167, -} -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bar { - One = 1, - Big = 2, -} diff --git a/tests/expectations/tests/prepend-enum-constified-variant.rs b/tests/expectations/tests/prepend-enum-constified-variant.rs deleted file mode 100644 index 7f3b674669..0000000000 --- a/tests/expectations/tests/prepend-enum-constified-variant.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const AV_CODEC_ID_TTF: AVCodecID = AVCodecID::AV_CODEC_ID_FIRST_UNKNOWN; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum AVCodecID { - AV_CODEC_ID_FIRST_UNKNOWN = 98304, -} diff --git a/tests/expectations/tests/prepend_enum_name.rs b/tests/expectations/tests/prepend_enum_name.rs deleted file mode 100644 index 96c7b617ae..0000000000 --- a/tests/expectations/tests/prepend_enum_name.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const FOO_BAR: foo = 0; -pub const FOO_BAZ: foo = 1; -pub type foo = u32; diff --git a/tests/expectations/tests/private.rs b/tests/expectations/tests/private.rs deleted file mode 100644 index 52da1ae4ed..0000000000 --- a/tests/expectations/tests/private.rs +++ /dev/null @@ -1,127 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct HasPrivate { - pub mNotPrivate: ::std::os::raw::c_int, - ///
- mIsPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_HasPrivate() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(HasPrivate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(HasPrivate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mNotPrivate as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(HasPrivate), - "::", - stringify!(mNotPrivate) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mIsPrivate as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(HasPrivate), - "::", - stringify!(mIsPrivate) - ) - ); -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct VeryPrivate { - mIsPrivate: ::std::os::raw::c_int, - mIsAlsoPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_VeryPrivate() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(VeryPrivate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(VeryPrivate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mIsPrivate as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(VeryPrivate), - "::", - stringify!(mIsPrivate) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mIsAlsoPrivate as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(VeryPrivate), - "::", - stringify!(mIsAlsoPrivate) - ) - ); -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct ContradictPrivate { - ///
- pub mNotPrivate: ::std::os::raw::c_int, - mIsPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContradictPrivate() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ContradictPrivate)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(ContradictPrivate)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mNotPrivate as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContradictPrivate), - "::", - stringify!(mNotPrivate) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mIsPrivate as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ContradictPrivate), - "::", - stringify!(mIsPrivate) - ) - ); -} diff --git a/tests/expectations/tests/public-dtor.rs b/tests/expectations/tests/public-dtor.rs deleted file mode 100644 index f551c2cbf5..0000000000 --- a/tests/expectations/tests/public-dtor.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct cv_String { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_cv_String() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(cv_String)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(cv_String)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN2cv6StringD1Ev"] - pub fn cv_String_String_destructor(this: *mut cv_String); -} -impl cv_String { - #[inline] - pub unsafe fn destruct(&mut self) { - cv_String_String_destructor(self) - } -} diff --git a/tests/expectations/tests/redeclaration.rs b/tests/expectations/tests/redeclaration.rs deleted file mode 100644 index 87df5e4ad7..0000000000 --- a/tests/expectations/tests/redeclaration.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - pub fn foo(); -} diff --git a/tests/expectations/tests/ref_argument_array.rs b/tests/expectations/tests/ref_argument_array.rs deleted file mode 100644 index 89ae83c993..0000000000 --- a/tests/expectations/tests/ref_argument_array.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const NSID_LENGTH: u32 = 10; -#[repr(C)] -pub struct nsID__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsID { - pub vtable_: *const nsID__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsID() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsID)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsID)) - ); -} -impl Default for nsID { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN4nsID16ToProvidedStringERA10_c"] - pub fn nsID_ToProvidedString( - this: *mut ::std::os::raw::c_void, - aDest: *mut [::std::os::raw::c_char; 10usize], - ); -} diff --git a/tests/expectations/tests/reparented_replacement.rs b/tests/expectations/tests/reparented_replacement.rs deleted file mode 100644 index 38f0cc220a..0000000000 --- a/tests/expectations/tests/reparented_replacement.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod foo { - #[allow(unused_imports)] - use self::super::super::root; - ///
- #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Bar { - pub bazz: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bazz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(bazz)) - ); - } - } - pub type ReferencesBar = root::foo::Bar; -} diff --git a/tests/expectations/tests/replace_template_alias.rs b/tests/expectations/tests/replace_template_alias.rs deleted file mode 100644 index 3ddde177d5..0000000000 --- a/tests/expectations/tests/replace_template_alias.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// But the replacement type does use T! -/// -///
-pub type JS_detail_MaybeWrapped = T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct JS_Rooted { - pub ptr: JS_detail_MaybeWrapped, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for JS_Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/replace_use.rs b/tests/expectations/tests/replace_use.rs deleted file mode 100644 index c5184b7775..0000000000 --- a/tests/expectations/tests/replace_use.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct nsTArray { - pub y: ::std::os::raw::c_uint, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Test { - pub a: nsTArray, -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Test), "::", stringify!(a)) - ); -} -#[test] -fn __bindgen_test_layout_nsTArray_open0_long_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of template specialization: ", stringify!(nsTArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(nsTArray) - ) - ); -} diff --git a/tests/expectations/tests/replaces_double.rs b/tests/expectations/tests/replaces_double.rs deleted file mode 100644 index 9d49052e67..0000000000 --- a/tests/expectations/tests/replaces_double.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Wrapper_Wrapped { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Wrapper_Wrapped { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type Wrapper_Type = Wrapper_Wrapped; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: Rooted_MaybeWrapped, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -///
-pub type Rooted_MaybeWrapped = T; -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/repr-align.rs b/tests/expectations/tests/repr-align.rs deleted file mode 100644 index 1827ca9d74..0000000000 --- a/tests/expectations/tests/repr-align.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(feature = "nightly")] - -#[repr(C)] -#[repr(align(8))] -#[derive(Debug, Default, Copy, Clone)] -pub struct a { - pub b: ::std::os::raw::c_int, - pub c: ::std::os::raw::c_int, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::
(), - 8usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(c)) - ); -} -#[repr(C)] -#[repr(align(8))] -#[derive(Debug, Default, Copy, Clone)] -pub struct b { - pub b: ::std::os::raw::c_int, - pub c: ::std::os::raw::c_int, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_b() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(b)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(b), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(b), "::", stringify!(c)) - ); -} diff --git a/tests/expectations/tests/resolved_type_def_function.rs b/tests/expectations/tests/resolved_type_def_function.rs deleted file mode 100644 index f400c9fed1..0000000000 --- a/tests/expectations/tests/resolved_type_def_function.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type FuncType = ::std::option::Option; -extern "C" { - pub fn Func(); -} diff --git a/tests/expectations/tests/same_struct_name_in_different_namespaces.rs b/tests/expectations/tests/same_struct_name_in_different_namespaces.rs deleted file mode 100644 index 9a8c1efa14..0000000000 --- a/tests/expectations/tests/same_struct_name_in_different_namespaces.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct JS_Zone { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct JS_shadow_Zone { - pub x: ::std::os::raw::c_int, - pub y: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_JS_shadow_Zone() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(JS_shadow_Zone)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(JS_shadow_Zone)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(JS_shadow_Zone), - "::", - stringify!(x) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).y as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(JS_shadow_Zone), - "::", - stringify!(y) - ) - ); -} diff --git a/tests/expectations/tests/sentry-defined-multiple-times.rs b/tests/expectations/tests/sentry-defined-multiple-times.rs deleted file mode 100644 index 887d84bb10..0000000000 --- a/tests/expectations/tests/sentry-defined-multiple-times.rs +++ /dev/null @@ -1,365 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod whatever { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Wrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Wrapper_sentry { - pub i_am_wrapper_sentry: ::std::os::raw::c_int, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct sentry { - pub i_am_plain_sentry: bool, - } - #[test] - fn bindgen_test_layout_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(sentry)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(sentry)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).i_am_plain_sentry as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sentry), - "::", - stringify!(i_am_plain_sentry) - ) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct NotTemplateWrapper { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_NotTemplateWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(NotTemplateWrapper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(NotTemplateWrapper)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct NotTemplateWrapper_sentry { - pub i_am_not_template_wrapper_sentry: ::std::os::raw::c_char, - } - #[test] - fn bindgen_test_layout_NotTemplateWrapper_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(NotTemplateWrapper_sentry)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(NotTemplateWrapper_sentry)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .i_am_not_template_wrapper_sentry as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(NotTemplateWrapper_sentry), - "::", - stringify!(i_am_not_template_wrapper_sentry) - ) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct InlineNotTemplateWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct InlineNotTemplateWrapper_sentry { - pub i_am_inline_not_template_wrapper_sentry: bool, - } - #[test] - fn bindgen_test_layout_InlineNotTemplateWrapper_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(InlineNotTemplateWrapper_sentry)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(InlineNotTemplateWrapper_sentry)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .i_am_inline_not_template_wrapper_sentry as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(InlineNotTemplateWrapper_sentry), - "::", - stringify!(i_am_inline_not_template_wrapper_sentry) - ) - ); - } - #[test] - fn bindgen_test_layout_InlineNotTemplateWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(InlineNotTemplateWrapper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(InlineNotTemplateWrapper)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct InlineTemplateWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct InlineTemplateWrapper_sentry { - pub i_am_inline_template_wrapper_sentry: ::std::os::raw::c_int, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleWrapper_InnerDoubleWrapper { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_OuterDoubleWrapper_InnerDoubleWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!( - "Size of: ", - stringify!(OuterDoubleWrapper_InnerDoubleWrapper) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of ", - stringify!(OuterDoubleWrapper_InnerDoubleWrapper) - ) - ); - } - #[test] - fn bindgen_test_layout_OuterDoubleWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(OuterDoubleWrapper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(OuterDoubleWrapper)) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleWrapper_InnerDoubleWrapper_sentry { - pub i_am_double_wrapper_sentry: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_OuterDoubleWrapper_InnerDoubleWrapper_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(OuterDoubleWrapper_InnerDoubleWrapper_sentry) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(OuterDoubleWrapper_InnerDoubleWrapper_sentry) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .i_am_double_wrapper_sentry as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(OuterDoubleWrapper_InnerDoubleWrapper_sentry), - "::", - stringify!(i_am_double_wrapper_sentry) - ) - ); - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleInlineWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleInlineWrapper_InnerDoubleInlineWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry { - pub i_am_double_wrapper_inline_sentry: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::< - OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry, - >())) - .i_am_double_wrapper_inline_sentry as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(OuterDoubleInlineWrapper_InnerDoubleInlineWrapper_sentry), - "::", - stringify!(i_am_double_wrapper_inline_sentry) - ) - ); - } - #[test] - fn bindgen_test_layout_OuterDoubleInlineWrapper_InnerDoubleInlineWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!( - "Size of: ", - stringify!(OuterDoubleInlineWrapper_InnerDoubleInlineWrapper) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of ", - stringify!(OuterDoubleInlineWrapper_InnerDoubleInlineWrapper) - ) - ); - } - #[test] - fn bindgen_test_layout_OuterDoubleInlineWrapper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(OuterDoubleInlineWrapper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(OuterDoubleInlineWrapper)) - ); - } - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OutsideNamespaceWrapper { - pub _address: u8, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct OutsideNamespaceWrapper_sentry { - pub i_am_outside_namespace_wrapper_sentry: ::std::os::raw::c_int, - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct sentry { - pub i_am_outside_namespace_sentry: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_sentry() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(sentry)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(sentry)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).i_am_outside_namespace_sentry as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sentry), - "::", - stringify!(i_am_outside_namespace_sentry) - ) - ); - } -} diff --git a/tests/expectations/tests/short-enums.rs b/tests/expectations/tests/short-enums.rs deleted file mode 100644 index a7739f21ec..0000000000 --- a/tests/expectations/tests/short-enums.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum one_byte_t { - SOME_VALUE = 1, -} -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum two_byte_t { - SOME_OTHER_VALUE = 256, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum four_byte_t { - SOME_BIGGER_VALUE = 16777216, -} diff --git a/tests/expectations/tests/size_t_template.rs b/tests/expectations/tests/size_t_template.rs deleted file mode 100644 index 8bc5430088..0000000000 --- a/tests/expectations/tests/size_t_template.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct C { - pub arr: [u32; 3usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arr as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(arr)) - ); -} diff --git a/tests/expectations/tests/struct_containing_forward_declared_struct.rs b/tests/expectations/tests/struct_containing_forward_declared_struct.rs deleted file mode 100644 index de2efda507..0000000000 --- a/tests/expectations/tests/struct_containing_forward_declared_struct.rs +++ /dev/null @@ -1,57 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct a { - pub val_a: *mut b, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).val_a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(val_a)) - ); -} -impl Default for a { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct b { - pub val_b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_b() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(b)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).val_b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(b), "::", stringify!(val_b)) - ); -} diff --git a/tests/expectations/tests/struct_typedef.rs b/tests/expectations/tests/struct_typedef.rs deleted file mode 100644 index f85aeb4c09..0000000000 --- a/tests/expectations/tests/struct_typedef.rs +++ /dev/null @@ -1,80 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct typedef_named_struct { - pub has_name: bool, -} -#[test] -fn bindgen_test_layout_typedef_named_struct() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(typedef_named_struct)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(typedef_named_struct)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).has_name as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(typedef_named_struct), - "::", - stringify!(has_name) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct _bindgen_ty_1 { - pub no_name: *mut ::std::os::raw::c_void, -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<_bindgen_ty_1>(), - 8usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<_bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_bindgen_ty_1>())).no_name as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(no_name) - ) - ); -} -impl Default for _bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type struct_ptr_t = *mut _bindgen_ty_1; -pub type struct_ptr_ptr_t = *mut *mut _bindgen_ty_1; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum typedef_named_enum { - ENUM_HAS_NAME = 1, -} -pub const ENUM_IS_ANON: _bindgen_ty_2 = _bindgen_ty_2::ENUM_IS_ANON; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_2 { - ENUM_IS_ANON = 0, -} -pub type enum_ptr_t = *mut _bindgen_ty_2; -pub type enum_ptr_ptr_t = *mut *mut _bindgen_ty_2; diff --git a/tests/expectations/tests/struct_typedef_ns.rs b/tests/expectations/tests/struct_typedef_ns.rs deleted file mode 100644 index 79fa38de43..0000000000 --- a/tests/expectations/tests/struct_typedef_ns.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod whatever { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] - pub struct typedef_struct { - pub foo: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout_typedef_struct() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(typedef_struct)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(typedef_struct)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(typedef_struct), - "::", - stringify!(foo) - ) - ); - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum typedef_enum { - BAR = 1, - } - } - pub mod _bindgen_mod_id_12 { - #[allow(unused_imports)] - use self::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] - pub struct _bindgen_ty_1 { - pub foo: ::std::os::raw::c_int, - } - #[test] - fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<_bindgen_ty_1>(), - 4usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<_bindgen_ty_1>(), - 4usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_bindgen_ty_1>())).foo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(foo) - ) - ); - } - pub type typedef_struct = root::_bindgen_mod_id_12::_bindgen_ty_1; - pub const _bindgen_mod_id_12_BAR: root::_bindgen_mod_id_12::_bindgen_ty_2 = - _bindgen_ty_2::BAR; - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum _bindgen_ty_2 { - BAR = 1, - } - pub use self::super::super::root::_bindgen_mod_id_12::_bindgen_ty_2 as typedef_enum; - } -} diff --git a/tests/expectations/tests/struct_with_anon_struct.rs b/tests/expectations/tests/struct_with_anon_struct.rs deleted file mode 100644 index 5dcdaf8c46..0000000000 --- a/tests/expectations/tests/struct_with_anon_struct.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/struct_with_anon_struct_array.rs b/tests/expectations/tests/struct_with_anon_struct_array.rs deleted file mode 100644 index 7af227a11b..0000000000 --- a/tests/expectations/tests/struct_with_anon_struct_array.rs +++ /dev/null @@ -1,113 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: [foo__bindgen_ty_1; 2usize], - pub baz: [[[foo__bindgen_ty_2; 4usize]; 3usize]; 2usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_2 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_2), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_2), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 208usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 16usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(baz)) - ); -} diff --git a/tests/expectations/tests/struct_with_anon_struct_pointer.rs b/tests/expectations/tests/struct_with_anon_struct_pointer.rs deleted file mode 100644 index 906ff46946..0000000000 --- a/tests/expectations/tests/struct_with_anon_struct_pointer.rs +++ /dev/null @@ -1,73 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: *mut foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_anon_union.rs b/tests/expectations/tests/struct_with_anon_union.rs deleted file mode 100644 index f7ddb3584d..0000000000 --- a/tests/expectations/tests/struct_with_anon_union.rs +++ /dev/null @@ -1,79 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_anon_union_1_0.rs b/tests/expectations/tests/struct_with_anon_union_1_0.rs deleted file mode 100644 index 7e2855c97b..0000000000 --- a/tests/expectations/tests/struct_with_anon_union_1_0.rs +++ /dev/null @@ -1,122 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/struct_with_anon_unnamed_struct.rs b/tests/expectations/tests/struct_with_anon_unnamed_struct.rs deleted file mode 100644 index b2baff9347..0000000000 --- a/tests/expectations/tests/struct_with_anon_unnamed_struct.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); -} diff --git a/tests/expectations/tests/struct_with_anon_unnamed_union.rs b/tests/expectations/tests/struct_with_anon_unnamed_union.rs deleted file mode 100644 index 378900198d..0000000000 --- a/tests/expectations/tests/struct_with_anon_unnamed_union.rs +++ /dev/null @@ -1,74 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct foo { - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_anon_unnamed_union_1_0.rs b/tests/expectations/tests/struct_with_anon_unnamed_union_1_0.rs deleted file mode 100644 index c7a73b1721..0000000000 --- a/tests/expectations/tests/struct_with_anon_unnamed_union_1_0.rs +++ /dev/null @@ -1,117 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs deleted file mode 100644 index 85f37e103b..0000000000 --- a/tests/expectations/tests/struct_with_bitfields.rs +++ /dev/null @@ -1,227 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct bitfield { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - pub e: ::std::os::raw::c_int, - pub _bitfield_2: __BindgenBitfieldUnit<[u8; 8usize], u32>, -} -#[test] -fn bindgen_test_layout_bitfield() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(bitfield)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bitfield)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).e as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(bitfield), - "::", - stringify!(e) - ) - ); -} -impl bitfield { - #[inline] - pub fn a(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } - } - #[inline] - pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn b(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } - } - #[inline] - pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(1usize, 1u8, val as u64) - } - } - #[inline] - pub fn c(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } - } - #[inline] - pub fn set_c(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(2usize, 1u8, val as u64) - } - } - #[inline] - pub fn d(&self) -> ::std::os::raw::c_ushort { - unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 2u8) as u16) } - } - #[inline] - pub fn set_d(&mut self, val: ::std::os::raw::c_ushort) { - unsafe { - let val: u16 = ::std::mem::transmute(val); - self._bitfield_1.set(6usize, 2u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - a: ::std::os::raw::c_ushort, - b: ::std::os::raw::c_ushort, - c: ::std::os::raw::c_ushort, - d: ::std::os::raw::c_ushort, - ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let a: u16 = unsafe { ::std::mem::transmute(a) }; - a as u64 - }); - __bindgen_bitfield_unit.set(1usize, 1u8, { - let b: u16 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit.set(2usize, 1u8, { - let c: u16 = unsafe { ::std::mem::transmute(c) }; - c as u64 - }); - __bindgen_bitfield_unit.set(6usize, 2u8, { - let d: u16 = unsafe { ::std::mem::transmute(d) }; - d as u64 - }); - __bindgen_bitfield_unit - } - #[inline] - pub fn f(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 2u8) as u32) } - } - #[inline] - pub fn set_f(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_2.set(0usize, 2u8, val as u64) - } - } - #[inline] - pub fn g(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_2.get(32usize, 32u8) as u32) } - } - #[inline] - pub fn set_g(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_2.set(32usize, 32u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_2( - f: ::std::os::raw::c_uint, - g: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 8usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 2u8, { - let f: u32 = unsafe { ::std::mem::transmute(f) }; - f as u64 - }); - __bindgen_bitfield_unit.set(32usize, 32u8, { - let g: u32 = unsafe { ::std::mem::transmute(g) }; - g as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/struct_with_derive_debug.rs b/tests/expectations/tests/struct_with_derive_debug.rs deleted file mode 100644 index 205e565df7..0000000000 --- a/tests/expectations/tests/struct_with_derive_debug.rs +++ /dev/null @@ -1,128 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct LittleArray { - pub a: [::std::os::raw::c_int; 32usize], -} -#[test] -fn bindgen_test_layout_LittleArray() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(LittleArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(LittleArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(LittleArray), - "::", - stringify!(a) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct BigArray { - pub a: [::std::os::raw::c_int; 33usize], -} -#[test] -fn bindgen_test_layout_BigArray() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(BigArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(BigArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(BigArray), - "::", - stringify!(a) - ) - ); -} -impl Default for BigArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct WithLittleArray { - pub a: LittleArray, -} -#[test] -fn bindgen_test_layout_WithLittleArray() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(WithLittleArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithLittleArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithLittleArray), - "::", - stringify!(a) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct WithBigArray { - pub a: BigArray, -} -#[test] -fn bindgen_test_layout_WithBigArray() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(WithBigArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray), - "::", - stringify!(a) - ) - ); -} -impl Default for WithBigArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_large_array.rs b/tests/expectations/tests/struct_with_large_array.rs deleted file mode 100644 index 43388edae8..0000000000 --- a/tests/expectations/tests/struct_with_large_array.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct S { - pub large_array: [::std::os::raw::c_char; 33usize], -} -#[test] -fn bindgen_test_layout_S() { - assert_eq!( - ::std::mem::size_of::(), - 33usize, - concat!("Size of: ", stringify!(S)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(S)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).large_array as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(S), - "::", - stringify!(large_array) - ) - ); -} -impl Default for S { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct ST { - pub large_array: [T; 33usize], - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for ST { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_nesting.rs b/tests/expectations/tests/struct_with_nesting.rs deleted file mode 100644 index f56c44a5f8..0000000000 --- a/tests/expectations/tests/struct_with_nesting.rs +++ /dev/null @@ -1,183 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct foo { - pub a: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1 { - pub b: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, - pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_1 { - pub c1: ::std::os::raw::c_ushort, - pub c2: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(c1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c2 as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(c2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_2 { - pub d1: ::std::os::raw::c_uchar, - pub d2: ::std::os::raw::c_uchar, - pub d3: ::std::os::raw::c_uchar, - pub d4: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d2 as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d3 as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d3) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d4 as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d4) - ) - ); -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/struct_with_nesting_1_0.rs b/tests/expectations/tests/struct_with_nesting_1_0.rs deleted file mode 100644 index ff65ea0349..0000000000 --- a/tests/expectations/tests/struct_with_nesting_1_0.rs +++ /dev/null @@ -1,236 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub a: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub b: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub __bindgen_anon_2: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_1 { - pub c1: ::std::os::raw::c_ushort, - pub c2: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(c1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c2 as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(c2) - ) - ); -} -impl Clone for foo__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_2 { - pub d1: ::std::os::raw::c_uchar, - pub d2: ::std::os::raw::c_uchar, - pub d3: ::std::os::raw::c_uchar, - pub d4: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d2 as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d3 as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d3) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).d4 as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(d4) - ) - ); -} -impl Clone for foo__bindgen_ty_1__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/struct_with_packing.rs b/tests/expectations/tests/struct_with_packing.rs deleted file mode 100644 index 410d8f4a04..0000000000 --- a/tests/expectations/tests/struct_with_packing.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C, packed)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct a { - pub b: ::std::os::raw::c_char, - pub c: ::std::os::raw::c_short, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!( - ::std::mem::size_of::(), - 3usize, - concat!("Size of: ", stringify!(a)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 1usize, - concat!("Offset of field: ", stringify!(a), "::", stringify!(c)) - ); -} diff --git a/tests/expectations/tests/struct_with_struct.rs b/tests/expectations/tests/struct_with_struct.rs deleted file mode 100644 index 95d66bf8f9..0000000000 --- a/tests/expectations/tests/struct_with_struct.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub x: ::std::os::raw::c_uint, - pub y: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(x) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).y as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(y) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} diff --git a/tests/expectations/tests/template-param-usage-0.rs b/tests/expectations/tests/template-param-usage-0.rs deleted file mode 100644 index d5ca7d7dac..0000000000 --- a/tests/expectations/tests/template-param-usage-0.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for UsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-10.rs b/tests/expectations/tests/template-param-usage-10.rs deleted file mode 100644 index 940be664bc..0000000000 --- a/tests/expectations/tests/template-param-usage-10.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DoublyIndirectUsage { - pub doubly_indirect: DoublyIndirectUsage_IndirectUsage, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -pub type DoublyIndirectUsage_Aliased = T; -pub type DoublyIndirectUsage_Typedefed = U; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DoublyIndirectUsage_IndirectUsage { - pub member: DoublyIndirectUsage_Aliased, - pub another: DoublyIndirectUsage_Typedefed, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for DoublyIndirectUsage_IndirectUsage { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for DoublyIndirectUsage { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-12.rs b/tests/expectations/tests/template-param-usage-12.rs deleted file mode 100644 index d6a540851b..0000000000 --- a/tests/expectations/tests/template-param-usage-12.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct BaseUsesT { - pub t: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for BaseUsesT { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct CrtpUsesU { - pub _base: BaseUsesT>, - pub usage: U, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for CrtpUsesU { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-13.rs b/tests/expectations/tests/template-param-usage-13.rs deleted file mode 100644 index 855c76fefd..0000000000 --- a/tests/expectations/tests/template-param-usage-13.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct BaseIgnoresT { - pub x: ::std::os::raw::c_int, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct CrtpUsesU { - pub _base: BaseIgnoresT, - pub usage: U, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for CrtpUsesU { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-14.rs b/tests/expectations/tests/template-param-usage-14.rs deleted file mode 100644 index 97dbba46fd..0000000000 --- a/tests/expectations/tests/template-param-usage-14.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct BaseIgnoresT { - pub x: ::std::os::raw::c_int, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct CrtpIgnoresU { - pub _base: BaseIgnoresT, - pub y: ::std::os::raw::c_int, -} -impl Default for CrtpIgnoresU { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-15.rs b/tests/expectations/tests/template-param-usage-15.rs deleted file mode 100644 index 405e8198e8..0000000000 --- a/tests/expectations/tests/template-param-usage-15.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct BaseUsesT { - pub usage: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for BaseUsesT { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct CrtpIgnoresU { - pub _base: BaseUsesT, - pub y: ::std::os::raw::c_int, -} -impl Default for CrtpIgnoresU { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-2.rs b/tests/expectations/tests/template-param-usage-2.rs deleted file mode 100644 index 24086724a0..0000000000 --- a/tests/expectations/tests/template-param-usage-2.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter_AlsoUsesTemplateParameter { - pub also: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for UsesTemplateParameter_AlsoUsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for UsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-3.rs b/tests/expectations/tests/template-param-usage-3.rs deleted file mode 100644 index 0e5d2fdf0e..0000000000 --- a/tests/expectations/tests/template-param-usage-3.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter_AlsoUsesTemplateParameterAndMore { - pub also: T, - pub more: U, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for UsesTemplateParameter_AlsoUsesTemplateParameterAndMore { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for UsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-4.rs b/tests/expectations/tests/template-param-usage-4.rs deleted file mode 100644 index af36754f00..0000000000 --- a/tests/expectations/tests/template-param-usage-4.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct UsesTemplateParameter { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct UsesTemplateParameter_DoesNotUseTemplateParameters { - pub x: ::std::os::raw::c_int, -} -impl Default for UsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-5.rs b/tests/expectations/tests/template-param-usage-5.rs deleted file mode 100644 index 46ae3513c6..0000000000 --- a/tests/expectations/tests/template-param-usage-5.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct IndirectlyUsesTemplateParameter { - pub aliased: IndirectlyUsesTemplateParameter_Aliased, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -pub type IndirectlyUsesTemplateParameter_Aliased = T; -impl Default for IndirectlyUsesTemplateParameter { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template-param-usage-7.rs b/tests/expectations/tests/template-param-usage-7.rs deleted file mode 100644 index b30c82b40e..0000000000 --- a/tests/expectations/tests/template-param-usage-7.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DoesNotUseU { - pub t: T, - pub v: V, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, - pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for DoesNotUseU { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type Alias = DoesNotUseU<::std::os::raw::c_int, ::std::os::raw::c_char>; diff --git a/tests/expectations/tests/template.rs b/tests/expectations/tests/template.rs deleted file mode 100644 index 6083265cf5..0000000000 --- a/tests/expectations/tests/template.rs +++ /dev/null @@ -1,855 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct Foo { - pub m_member: T, - pub m_member_ptr: *mut T, - pub m_member_arr: [T; 1usize], - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct B { - pub m_member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for B { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_Z3bar3FooIiiE"] - pub fn bar(foo: Foo<::std::os::raw::c_int>); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct mozilla_Foo { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct C { - pub mB: B<::std::os::raw::c_uint>, - pub mBConstPtr: B<*const ::std::os::raw::c_int>, - pub mBConstStructPtr: B<*const mozilla_Foo>, - pub mBConstStructPtrArray: B<[*const mozilla_Foo; 1usize]>, - pub mBConst: B<::std::os::raw::c_int>, - pub mBVolatile: B<::std::os::raw::c_int>, - pub mBConstBool: B, - pub mBConstChar: B, - pub mBArray: B<[::std::os::raw::c_int; 1usize]>, - pub mBPtrArray: B<[*mut ::std::os::raw::c_int; 1usize]>, - pub mBArrayPtr: B<*mut [::std::os::raw::c_int; 1usize]>, - pub mBRef: B<*mut ::std::os::raw::c_int>, - pub mBConstRef: B<*const ::std::os::raw::c_int>, - pub mPtrRef: B<*mut *mut ::std::os::raw::c_int>, - pub mArrayRef: B<*mut [::std::os::raw::c_int; 1usize]>, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 96usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mB as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(mB)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstPtr as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstPtr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstStructPtr as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstStructPtr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstStructPtrArray as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstStructPtrArray) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConst as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConst) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBVolatile as *const _ as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBVolatile) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstBool as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstBool) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstChar as *const _ as usize }, - 42usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstChar) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBArray as *const _ as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBArray) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBPtrArray as *const _ as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBPtrArray) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBArrayPtr as *const _ as usize }, - 56usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBArrayPtr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBRef as *const _ as usize }, - 64usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(mBRef)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBConstRef as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mBConstRef) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mPtrRef as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mPtrRef) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mArrayRef as *const _ as usize }, - 88usize, - concat!( - "Offset of field: ", - stringify!(C), - "::", - stringify!(mArrayRef) - ) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct D { - pub m_foo: D_MyFoo, -} -pub type D_MyFoo = Foo<::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct D_U { - pub m_nested_foo: D_MyFoo, - pub m_baz: Z, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for D_U { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for D { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Rooted { - pub prev: *mut T, - pub next: *mut Rooted<*mut ::std::os::raw::c_void>, - pub ptr: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RootedContainer { - pub root: Rooted<*mut ::std::os::raw::c_void>, -} -#[test] -fn bindgen_test_layout_RootedContainer() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(RootedContainer)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(RootedContainer)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).root as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(RootedContainer), - "::", - stringify!(root) - ) - ); -} -impl Default for RootedContainer { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct WithDtor { - pub member: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for WithDtor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct PODButContainsDtor { - pub member: WithDtorIntFwd, -} -#[test] -fn bindgen_test_layout_PODButContainsDtor() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(PODButContainsDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(PODButContainsDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(PODButContainsDtor), - "::", - stringify!(member) - ) - ); -} -impl Default for PODButContainsDtor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -///
-#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Opaque { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct POD { - pub opaque_member: u32, -} -#[test] -fn bindgen_test_layout_POD() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(POD)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(POD)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).opaque_member as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(POD), - "::", - stringify!(opaque_member) - ) - ); -} -///
-#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NestedReplaced { - pub buff: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for NestedReplaced { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NestedBase { - pub buff: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for NestedBase { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NestedContainer { - pub c: T, - pub nested: NestedReplaced, - pub inc: Incomplete, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for NestedContainer { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Incomplete { - pub d: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Incomplete { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Untemplated { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Untemplated() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Untemplated)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Untemplated)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Templated { - pub m_untemplated: Untemplated, -} -/// If the replacement doesn't happen at the parse level the container would be -/// copy and the replacement wouldn't, so this wouldn't compile. -/// -///
-#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct ReplacedWithoutDestructor { - pub buff: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for ReplacedWithoutDestructor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct ShouldNotBeCopiable { - pub m_member: ReplacedWithoutDestructor, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for ShouldNotBeCopiable { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct ShouldNotBeCopiableAsWell { - pub m_member: ReplacedWithoutDestructorFwd, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for ShouldNotBeCopiableAsWell { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -/// If the replacement doesn't happen at the parse level the container would be -/// copy and the replacement wouldn't, so this wouldn't compile. -/// -///
-#[repr(C)] -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct ReplacedWithoutDestructorFwd { - pub buff: *mut T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for ReplacedWithoutDestructorFwd { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_Foo_open0_int_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(Foo<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(Foo<::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_unsigned_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(B<::std::os::raw::c_uint>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<::std::os::raw::c_uint>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ptr_const_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*const ::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*const ::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ptr_const_mozilla__Foo_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*const mozilla_Foo>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*const mozilla_Foo>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_array1_ptr_const_mozilla__Foo_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<[*const mozilla_Foo; 1usize]>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<[*const mozilla_Foo; 1usize]>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_const_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(B<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_volatile_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(B<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_const_bool_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 1usize, - concat!("Size of template specialization: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::>(), - 1usize, - concat!( - "Alignment of template specialization: ", - stringify!(B) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_const_char16_t_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 2usize, - concat!("Size of template specialization: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::>(), - 2usize, - concat!("Alignment of template specialization: ", stringify!(B)) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_array1_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(B<[::std::os::raw::c_int; 1usize]>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<[::std::os::raw::c_int; 1usize]>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_array1_ptr_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<[*mut ::std::os::raw::c_int; 1usize]>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<[*mut ::std::os::raw::c_int; 1usize]>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ptr_array1_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*mut [::std::os::raw::c_int; 1usize]>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*mut [::std::os::raw::c_int; 1usize]>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ref_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*mut ::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*mut ::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ref_const_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*const ::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*const ::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ref_ptr_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*mut *mut ::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*mut *mut ::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_B_open0_ref_array1_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(B<*mut [::std::os::raw::c_int; 1usize]>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(B<*mut [::std::os::raw::c_int; 1usize]>) - ) - ); -} -#[test] -fn __bindgen_test_layout_Foo_open0_int_int_close0_instantiation_1() { - assert_eq!( - ::std::mem::size_of::>(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(Foo<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(Foo<::std::os::raw::c_int>) - ) - ); -} -#[test] -fn __bindgen_test_layout_Rooted_open0_ptr_void_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(Rooted<*mut ::std::os::raw::c_void>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(Rooted<*mut ::std::os::raw::c_void>) - ) - ); -} -#[test] -fn __bindgen_test_layout_Rooted_open0_ptr_void_close0_instantiation_1() { - assert_eq!( - ::std::mem::size_of::>(), - 24usize, - concat!( - "Size of template specialization: ", - stringify!(Rooted<*mut ::std::os::raw::c_void>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(Rooted<*mut ::std::os::raw::c_void>) - ) - ); -} -#[test] -fn __bindgen_test_layout_WithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 4usize, - concat!( - "Size of template specialization: ", - stringify!(WithDtor<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 4usize, - concat!( - "Alignment of template specialization: ", - stringify!(WithDtor<::std::os::raw::c_int>) - ) - ); -} diff --git a/tests/expectations/tests/template_alias.rs b/tests/expectations/tests/template_alias.rs deleted file mode 100644 index 9b66adf64e..0000000000 --- a/tests/expectations/tests/template_alias.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type JS_detail_Wrapped = T; -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct JS_Rooted { - pub ptr: JS_detail_Wrapped, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for JS_Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/template_alias_basic.rs b/tests/expectations/tests/template_alias_basic.rs deleted file mode 100644 index 29f3b7c7cf..0000000000 --- a/tests/expectations/tests/template_alias_basic.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type Wrapped = T; diff --git a/tests/expectations/tests/template_partial_specification.rs b/tests/expectations/tests/template_partial_specification.rs deleted file mode 100644 index 5dcc6c4008..0000000000 --- a/tests/expectations/tests/template_partial_specification.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] diff --git a/tests/expectations/tests/template_typedef_transitive_param.rs b/tests/expectations/tests/template_typedef_transitive_param.rs deleted file mode 100644 index 311dd97441..0000000000 --- a/tests/expectations/tests/template_typedef_transitive_param.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Wrapper { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Wrapper_Wrapped { - pub t: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Wrapper_Wrapped { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type Wrapper_Type = Wrapper_Wrapped; diff --git a/tests/expectations/tests/templatized-bitfield.rs b/tests/expectations/tests/templatized-bitfield.rs deleted file mode 100644 index 68ab6716fd..0000000000 --- a/tests/expectations/tests/templatized-bitfield.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - - -/// We don't get a layout for this bitfield, since we don't know what `T` will -/// be, so we cannot allocate bitfield units. The best thing we can do is make -/// the struct opaque. -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct TemplatizedBitfield { - pub _address: u8, -} diff --git a/tests/expectations/tests/test_multiple_header_calls_in_builder.rs b/tests/expectations/tests/test_multiple_header_calls_in_builder.rs deleted file mode 100644 index 94504951d7..0000000000 --- a/tests/expectations/tests/test_multiple_header_calls_in_builder.rs +++ /dev/null @@ -1,162 +0,0 @@ -/* automatically generated by rust-bindgen */ - -extern "C" { - #[link_name = "\u{1}foo"] - pub static mut foo: - ::std::option::Option< - unsafe extern "C" fn(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) - -> ::std::os::raw::c_int, - >; -} -pub type Char = ::std::os::raw::c_char; -pub type SChar = ::std::os::raw::c_schar; -pub type UChar = ::std::os::raw::c_uchar; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Test { - pub ch: ::std::os::raw::c_char, - pub u: ::std::os::raw::c_uchar, - pub d: ::std::os::raw::c_schar, - pub cch: ::std::os::raw::c_char, - pub cu: ::std::os::raw::c_uchar, - pub cd: ::std::os::raw::c_schar, - pub Cch: Char, - pub Cu: UChar, - pub Cd: SChar, - pub Ccch: Char, - pub Ccu: UChar, - pub Ccd: SChar, -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).ch as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(ch) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(u) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(d) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cch as *const _ as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(cch) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cu as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(cu) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).cd as *const _ as usize }, - 5usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(cd) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cch as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Cch) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cu as *const _ as usize }, - 7usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Cu) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Cd as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Cd) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccch as *const _ as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Ccch) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccu as *const _ as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Ccu) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Ccd as *const _ as usize }, - 11usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(Ccd) - ) - ); -} diff --git a/tests/expectations/tests/type-referenced-by-whitelisted-function.rs b/tests/expectations/tests/type-referenced-by-whitelisted-function.rs deleted file mode 100644 index 712a850833..0000000000 --- a/tests/expectations/tests/type-referenced-by-whitelisted-function.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct dl_phdr_info { - pub x: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_dl_phdr_info() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(dl_phdr_info)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(dl_phdr_info)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).x as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(dl_phdr_info), - "::", - stringify!(x) - ) - ); -} -extern "C" { - pub fn dl_iterate_phdr(arg1: *mut dl_phdr_info) -> ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/type_alias_empty.rs b/tests/expectations/tests/type_alias_empty.rs deleted file mode 100644 index d0f18dedfe..0000000000 --- a/tests/expectations/tests/type_alias_empty.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type bool_constant = u8; diff --git a/tests/expectations/tests/type_alias_partial_template_especialization.rs b/tests/expectations/tests/type_alias_partial_template_especialization.rs deleted file mode 100644 index 0a2e80fb2d..0000000000 --- a/tests/expectations/tests/type_alias_partial_template_especialization.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type MaybeWrapped
= A; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: MaybeWrapped, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Rooted { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/typedefd-array-as-function-arg.rs b/tests/expectations/tests/typedefd-array-as-function-arg.rs deleted file mode 100644 index e4e1cba5fa..0000000000 --- a/tests/expectations/tests/typedefd-array-as-function-arg.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub type myVector3 = [f32; 3usize]; -extern "C" { - pub fn modifyVectorFunc(v: *mut f32); -} diff --git a/tests/expectations/tests/typeref.rs b/tests/expectations/tests/typeref.rs deleted file mode 100644 index d533b9fb00..0000000000 --- a/tests/expectations/tests/typeref.rs +++ /dev/null @@ -1,153 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct mozilla_FragmentOrURL { - pub mIsLocalRef: bool, -} -#[test] -fn bindgen_test_layout_mozilla_FragmentOrURL() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(mozilla_FragmentOrURL)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(mozilla_FragmentOrURL)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mIsLocalRef as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mozilla_FragmentOrURL), - "::", - stringify!(mIsLocalRef) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct mozilla_Position { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_mozilla_Position() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(mozilla_Position)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(mozilla_Position)) - ); -} -#[repr(C)] -pub struct mozilla_StyleShapeSource { - pub __bindgen_anon_1: mozilla_StyleShapeSource__bindgen_ty_1, -} -#[repr(C)] -pub union mozilla_StyleShapeSource__bindgen_ty_1 { - pub mPosition: *mut mozilla_Position, - pub mFragmentOrURL: *mut mozilla_FragmentOrURL, - _bindgen_union_align: u64, -} -impl Default for mozilla_StyleShapeSource__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for mozilla_StyleShapeSource { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Bar { - pub mFoo: *mut nsFoo, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFoo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(mFoo)) - ); -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct nsFoo { - pub mBar: mozilla_StyleShapeSource, -} -#[test] -fn bindgen_test_layout_nsFoo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsFoo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsFoo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsFoo), - "::", - stringify!(mBar) - ) - ); -} -impl Default for nsFoo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn __bindgen_test_layout_mozilla_StyleShapeSource_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(mozilla_StyleShapeSource) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(mozilla_StyleShapeSource) - ) - ); -} diff --git a/tests/expectations/tests/typeref_1_0.rs b/tests/expectations/tests/typeref_1_0.rs deleted file mode 100644 index 649d41fab7..0000000000 --- a/tests/expectations/tests/typeref_1_0.rs +++ /dev/null @@ -1,204 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct mozilla_FragmentOrURL { - pub mIsLocalRef: bool, -} -#[test] -fn bindgen_test_layout_mozilla_FragmentOrURL() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(mozilla_FragmentOrURL)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(mozilla_FragmentOrURL)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mIsLocalRef as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mozilla_FragmentOrURL), - "::", - stringify!(mIsLocalRef) - ) - ); -} -impl Clone for mozilla_FragmentOrURL { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct mozilla_Position { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_mozilla_Position() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(mozilla_Position)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(mozilla_Position)) - ); -} -impl Clone for mozilla_Position { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct mozilla_StyleShapeSource { - pub __bindgen_anon_1: mozilla_StyleShapeSource__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct mozilla_StyleShapeSource__bindgen_ty_1 { - pub mPosition: __BindgenUnionField<*mut mozilla_Position>, - pub mFragmentOrURL: __BindgenUnionField<*mut mozilla_FragmentOrURL>, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct Bar { - pub mFoo: *mut nsFoo, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFoo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(Bar), "::", stringify!(mFoo)) - ); -} -impl Clone for Bar { - fn clone(&self) -> Self { - *self - } -} -impl Default for Bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct nsFoo { - pub mBar: mozilla_StyleShapeSource, -} -#[test] -fn bindgen_test_layout_nsFoo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsFoo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsFoo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsFoo), - "::", - stringify!(mBar) - ) - ); -} -impl Clone for nsFoo { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn __bindgen_test_layout_mozilla_StyleShapeSource_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(mozilla_StyleShapeSource) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(mozilla_StyleShapeSource) - ) - ); -} diff --git a/tests/expectations/tests/underscore.rs b/tests/expectations/tests/underscore.rs deleted file mode 100644 index c4bd288cb4..0000000000 --- a/tests/expectations/tests/underscore.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const __: ::std::os::raw::c_int = 10; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct ptr_t { - pub __: [::std::os::raw::c_uchar; 8usize], -} -#[test] -fn bindgen_test_layout_ptr_t() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ptr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ptr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__ as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(ptr_t), "::", stringify!(__)) - ); -} diff --git a/tests/expectations/tests/union-in-ns.rs b/tests/expectations/tests/union-in-ns.rs deleted file mode 100644 index ee4ac07c45..0000000000 --- a/tests/expectations/tests/union-in-ns.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Copy, Clone)] - pub union bar { - pub baz: ::std::os::raw::c_int, - _bindgen_union_align: u32, - } - #[test] - fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(baz)) - ); - } - impl Default for bar { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } - } -} diff --git a/tests/expectations/tests/union-in-ns_1_0.rs b/tests/expectations/tests/union-in-ns_1_0.rs deleted file mode 100644 index 8635727f0d..0000000000 --- a/tests/expectations/tests/union-in-ns_1_0.rs +++ /dev/null @@ -1,83 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[repr(C)] - pub struct __BindgenUnionField(::std::marker::PhantomData); - impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } - } - impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } - } - impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } - } - impl ::std::marker::Copy for __BindgenUnionField {} - impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } - } - impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} - } - impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } - } - impl ::std::cmp::Eq for __BindgenUnionField {} - #[allow(unused_imports)] - use self::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy)] - pub struct bar { - pub baz: root::__BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, - } - #[test] - fn bindgen_test_layout_bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(bar), "::", stringify!(baz)) - ); - } - impl Clone for bar { - fn clone(&self) -> Self { - *self - } - } -} diff --git a/tests/expectations/tests/union_bitfield.rs b/tests/expectations/tests/union_bitfield.rs deleted file mode 100644 index 1f75ee4de3..0000000000 --- a/tests/expectations/tests/union_bitfield.rs +++ /dev/null @@ -1,197 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union U4 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_U4() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(U4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(U4)) - ); -} -impl Default for U4 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl U4 { - #[inline] - pub fn derp(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } - } - #[inline] - pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(derp: ::std::os::raw::c_uint) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let derp: u32 = unsafe { ::std::mem::transmute(derp) }; - derp as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union B { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B)) - ); -} -impl Default for B { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl B { - #[inline] - pub fn foo(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 31u8) as u32) } - } - #[inline] - pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 31u8, val as u64) - } - } - #[inline] - pub fn bar(&self) -> ::std::os::raw::c_uchar { - unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } - } - #[inline] - pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(31usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - foo: ::std::os::raw::c_uint, - bar: ::std::os::raw::c_uchar, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 31u8, { - let foo: u32 = unsafe { ::std::mem::transmute(foo) }; - foo as u64 - }); - __bindgen_bitfield_unit.set(31usize, 1u8, { - let bar: u8 = unsafe { ::std::mem::transmute(bar) }; - bar as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/union_bitfield_1_0.rs b/tests/expectations/tests/union_bitfield_1_0.rs deleted file mode 100644 index a85fad4c2e..0000000000 --- a/tests/expectations/tests/union_bitfield_1_0.rs +++ /dev/null @@ -1,264 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct U4 { - pub _bitfield_1: __BindgenUnionField<__BindgenBitfieldUnit<[u8; 1usize], u8>>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_U4() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(U4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(U4)) - ); -} -impl Clone for U4 { - fn clone(&self) -> Self { - *self - } -} -impl U4 { - #[inline] - pub fn derp(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.as_ref().get(0usize, 1u8) as u32) } - } - #[inline] - pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.as_mut().set(0usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(derp: ::std::os::raw::c_uint) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 1u8, { - let derp: u32 = unsafe { ::std::mem::transmute(derp) }; - derp as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct B { - pub _bitfield_1: __BindgenUnionField<__BindgenBitfieldUnit<[u8; 4usize], u32>>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(B)) - ); -} -impl Clone for B { - fn clone(&self) -> Self { - *self - } -} -impl B { - #[inline] - pub fn foo(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.as_ref().get(0usize, 31u8) as u32) } - } - #[inline] - pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.as_mut().set(0usize, 31u8, val as u64) - } - } - #[inline] - pub fn bar(&self) -> ::std::os::raw::c_uchar { - unsafe { ::std::mem::transmute(self._bitfield_1.as_ref().get(31usize, 1u8) as u8) } - } - #[inline] - pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.as_mut().set(31usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - foo: ::std::os::raw::c_uint, - bar: ::std::os::raw::c_uchar, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 31u8, { - let foo: u32 = unsafe { ::std::mem::transmute(foo) }; - foo as u64 - }); - __bindgen_bitfield_unit.set(31usize, 1u8, { - let bar: u8 = unsafe { ::std::mem::transmute(bar) }; - bar as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Copy)] -pub struct HasBigBitfield { - pub _bitfield_1: __BindgenUnionField<__BindgenBitfieldUnit<[u8; 16usize], u64>>, - pub bindgen_union_field: [u8; 16usize], -} -#[test] -fn bindgen_test_layout_HasBigBitfield() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(HasBigBitfield)) - ); -} -impl Clone for HasBigBitfield { - fn clone(&self) -> Self { - *self - } -} -impl Default for HasBigBitfield { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_dtor.rs b/tests/expectations/tests/union_dtor.rs deleted file mode 100644 index 69359e64f7..0000000000 --- a/tests/expectations/tests/union_dtor.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub union UnionWithDtor { - pub mFoo: ::std::os::raw::c_int, - pub mBar: *mut ::std::os::raw::c_void, - _bindgen_union_align: u64, -} -#[test] -fn bindgen_test_layout_UnionWithDtor() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(UnionWithDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(UnionWithDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFoo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(UnionWithDtor), - "::", - stringify!(mFoo) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(UnionWithDtor), - "::", - stringify!(mBar) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN13UnionWithDtorD1Ev"] - pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor); -} -impl Default for UnionWithDtor { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl UnionWithDtor { - #[inline] - pub unsafe fn destruct(&mut self) { - UnionWithDtor_UnionWithDtor_destructor(self) - } -} diff --git a/tests/expectations/tests/union_dtor_1_0.rs b/tests/expectations/tests/union_dtor_1_0.rs deleted file mode 100644 index 77a734272b..0000000000 --- a/tests/expectations/tests/union_dtor_1_0.rs +++ /dev/null @@ -1,99 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default)] -pub struct UnionWithDtor { - pub mFoo: __BindgenUnionField<::std::os::raw::c_int>, - pub mBar: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout_UnionWithDtor() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(UnionWithDtor)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(UnionWithDtor)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFoo as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(UnionWithDtor), - "::", - stringify!(mFoo) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mBar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(UnionWithDtor), - "::", - stringify!(mBar) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN13UnionWithDtorD1Ev"] - pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor); -} -impl UnionWithDtor { - #[inline] - pub unsafe fn destruct(&mut self) { - UnionWithDtor_UnionWithDtor_destructor(self) - } -} diff --git a/tests/expectations/tests/union_fields.rs b/tests/expectations/tests/union_fields.rs deleted file mode 100644 index 38657d05a2..0000000000 --- a/tests/expectations/tests/union_fields.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union nsStyleUnion { - pub mInt: ::std::os::raw::c_int, - pub mFloat: f32, - pub mPointer: *mut ::std::os::raw::c_void, - _bindgen_union_align: u64, -} -#[test] -fn bindgen_test_layout_nsStyleUnion() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsStyleUnion)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsStyleUnion)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mInt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mInt) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFloat as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mFloat) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mPointer as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mPointer) - ) - ); -} -impl Default for nsStyleUnion { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_fields_1_0.rs b/tests/expectations/tests/union_fields_1_0.rs deleted file mode 100644 index 090f1662d2..0000000000 --- a/tests/expectations/tests/union_fields_1_0.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq)] -pub struct nsStyleUnion { - pub mInt: __BindgenUnionField<::std::os::raw::c_int>, - pub mFloat: __BindgenUnionField, - pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout_nsStyleUnion() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsStyleUnion)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsStyleUnion)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mInt as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mInt) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFloat as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mFloat) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mPointer as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(nsStyleUnion), - "::", - stringify!(mPointer) - ) - ); -} -impl Clone for nsStyleUnion { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_template.rs b/tests/expectations/tests/union_template.rs deleted file mode 100644 index 515d568867..0000000000 --- a/tests/expectations/tests/union_template.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct NastyStruct { - pub mIsSome: bool, - pub mStorage: NastyStruct__bindgen_ty_1, - pub __bindgen_anon_1: NastyStruct__bindgen_ty_2, -} -#[repr(C)] -pub union NastyStruct__bindgen_ty_1 { - pub mFoo: *mut ::std::os::raw::c_void, - pub mDummy: ::std::os::raw::c_ulong, - _bindgen_union_align: u64, -} -impl Default for NastyStruct__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub union NastyStruct__bindgen_ty_2 { - pub wat: ::std::os::raw::c_short, - pub wut: *mut ::std::os::raw::c_int, - _bindgen_union_align: u64, -} -impl Default for NastyStruct__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for NastyStruct { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub union Whatever { - pub mTPtr: *mut ::std::os::raw::c_void, - pub mInt: ::std::os::raw::c_int, - _bindgen_union_align: u64, -} -impl Default for Whatever { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_template_1_0.rs b/tests/expectations/tests/union_template_1_0.rs deleted file mode 100644 index 7b350b0786..0000000000 --- a/tests/expectations/tests/union_template_1_0.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NastyStruct { - pub mIsSome: bool, - pub mStorage: NastyStruct__bindgen_ty_1, - pub __bindgen_anon_1: NastyStruct__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NastyStruct__bindgen_ty_1 { - pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NastyStruct__bindgen_ty_2 { - pub wat: __BindgenUnionField<::std::os::raw::c_short>, - pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Whatever { - pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub mInt: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u64, -} diff --git a/tests/expectations/tests/union_with_anon_struct.rs b/tests/expectations/tests/union_with_anon_struct.rs deleted file mode 100644 index dbffb17c81..0000000000 --- a/tests/expectations/tests/union_with_anon_struct.rs +++ /dev/null @@ -1,74 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo { - pub bar: foo__bindgen_ty_1, - _bindgen_union_align: [u32; 2usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_anon_struct_1_0.rs b/tests/expectations/tests/union_with_anon_struct_1_0.rs deleted file mode 100644 index cdd1713637..0000000000 --- a/tests/expectations/tests/union_with_anon_struct_1_0.rs +++ /dev/null @@ -1,122 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: __BindgenUnionField, - pub bindgen_union_field: [u32; 2usize], -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/tests/expectations/tests/union_with_anon_struct_bitfield.rs deleted file mode 100644 index 9e6717415e..0000000000 --- a/tests/expectations/tests/union_with_anon_struct_bitfield.rs +++ /dev/null @@ -1,175 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo { - pub a: ::std::os::raw::c_int, - pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); -} -impl foo__bindgen_ty_1 { - #[inline] - pub fn b(&self) -> ::std::os::raw::c_int { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u32) } - } - #[inline] - pub fn set_b(&mut self, val: ::std::os::raw::c_int) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 7u8, val as u64) - } - } - #[inline] - pub fn c(&self) -> ::std::os::raw::c_int { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 25u8) as u32) } - } - #[inline] - pub fn set_c(&mut self, val: ::std::os::raw::c_int) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 25u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - b: ::std::os::raw::c_int, - c: ::std::os::raw::c_int, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 7u8, { - let b: u32 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit.set(7usize, 25u8, { - let c: u32 = unsafe { ::std::mem::transmute(c) }; - c as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs b/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs deleted file mode 100644 index f2d63c3e8c..0000000000 --- a/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs +++ /dev/null @@ -1,223 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, - pub __bindgen_align: [u32; 0usize], -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -impl foo__bindgen_ty_1 { - #[inline] - pub fn b(&self) -> ::std::os::raw::c_int { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u32) } - } - #[inline] - pub fn set_b(&mut self, val: ::std::os::raw::c_int) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 7u8, val as u64) - } - } - #[inline] - pub fn c(&self) -> ::std::os::raw::c_int { - unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 25u8) as u32) } - } - #[inline] - pub fn set_c(&mut self, val: ::std::os::raw::c_int) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(7usize, 25u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - b: ::std::os::raw::c_int, - c: ::std::os::raw::c_int, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u32> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u32> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 7u8, { - let b: u32 = unsafe { ::std::mem::transmute(b) }; - b as u64 - }); - __bindgen_bitfield_unit.set(7usize, 25u8, { - let c: u32 = unsafe { ::std::mem::transmute(c) }; - c as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_with_anon_union.rs b/tests/expectations/tests/union_with_anon_union.rs deleted file mode 100644 index 43581d8b91..0000000000 --- a/tests/expectations/tests/union_with_anon_union.rs +++ /dev/null @@ -1,80 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo { - pub bar: foo__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_anon_union_1_0.rs b/tests/expectations/tests/union_with_anon_union_1_0.rs deleted file mode 100644 index 2ccf17392a..0000000000 --- a/tests/expectations/tests/union_with_anon_union_1_0.rs +++ /dev/null @@ -1,123 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub bar: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_struct.rs b/tests/expectations/tests/union_with_anon_unnamed_struct.rs deleted file mode 100644 index 738aade3b3..0000000000 --- a/tests/expectations/tests/union_with_anon_unnamed_struct.rs +++ /dev/null @@ -1,102 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union pixel { - pub rgba: ::std::os::raw::c_uint, - pub __bindgen_anon_1: pixel__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] -pub struct pixel__bindgen_ty_1 { - pub r: ::std::os::raw::c_uchar, - pub g: ::std::os::raw::c_uchar, - pub b: ::std::os::raw::c_uchar, - pub a: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_pixel__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pixel__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(pixel__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).r as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(r) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).g as *const _ as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(g) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(a) - ) - ); -} -#[test] -fn bindgen_test_layout_pixel() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pixel)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pixel)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rgba as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pixel), - "::", - stringify!(rgba) - ) - ); -} -impl Default for pixel { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_struct_1_0.rs b/tests/expectations/tests/union_with_anon_unnamed_struct_1_0.rs deleted file mode 100644 index cbfd47024f..0000000000 --- a/tests/expectations/tests/union_with_anon_unnamed_struct_1_0.rs +++ /dev/null @@ -1,150 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct pixel { - pub rgba: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct pixel__bindgen_ty_1 { - pub r: ::std::os::raw::c_uchar, - pub g: ::std::os::raw::c_uchar, - pub b: ::std::os::raw::c_uchar, - pub a: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_pixel__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pixel__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(pixel__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).r as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(r) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).g as *const _ as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(g) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(pixel__bindgen_ty_1), - "::", - stringify!(a) - ) - ); -} -impl Clone for pixel__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_pixel() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pixel)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pixel)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rgba as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pixel), - "::", - stringify!(rgba) - ) - ); -} -impl Clone for pixel { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_union.rs b/tests/expectations/tests/union_with_anon_unnamed_union.rs deleted file mode 100644 index 35c9028570..0000000000 --- a/tests/expectations/tests/union_with_anon_unnamed_union.rs +++ /dev/null @@ -1,81 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo { - pub a: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1 { - pub b: ::std::os::raw::c_ushort, - pub c: ::std::os::raw::c_uchar, - _bindgen_union_align: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(c) - ) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_union_1_0.rs b/tests/expectations/tests/union_with_anon_unnamed_union_1_0.rs deleted file mode 100644 index 4505473988..0000000000 --- a/tests/expectations/tests/union_with_anon_unnamed_union_1_0.rs +++ /dev/null @@ -1,124 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub c: __BindgenUnionField<::std::os::raw::c_uchar>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1), - "::", - stringify!(c) - ) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/union_with_big_member.rs b/tests/expectations/tests/union_with_big_member.rs deleted file mode 100644 index 64ce4d0feb..0000000000 --- a/tests/expectations/tests/union_with_big_member.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union WithBigArray { - pub a: ::std::os::raw::c_int, - pub b: [::std::os::raw::c_int; 33usize], - _bindgen_union_align: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigArray() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(WithBigArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray), - "::", - stringify!(b) - ) - ); -} -impl Default for WithBigArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union WithBigArray2 { - pub a: ::std::os::raw::c_int, - pub b: [::std::os::raw::c_char; 33usize], - _bindgen_union_align: [u32; 9usize], -} -#[test] -fn bindgen_test_layout_WithBigArray2() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(WithBigArray2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigArray2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray2), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray2), - "::", - stringify!(b) - ) - ); -} -impl Default for WithBigArray2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union WithBigMember { - pub a: ::std::os::raw::c_int, - pub b: WithBigArray, - _bindgen_union_align: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigMember() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(WithBigMember)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigMember)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigMember), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigMember), - "::", - stringify!(b) - ) - ); -} -impl Default for WithBigMember { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_big_member_1_0.rs b/tests/expectations/tests/union_with_big_member_1_0.rs deleted file mode 100644 index c41e64e2c5..0000000000 --- a/tests/expectations/tests/union_with_big_member_1_0.rs +++ /dev/null @@ -1,194 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Copy)] -pub struct WithBigArray { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField<[::std::os::raw::c_int; 33usize]>, - pub bindgen_union_field: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigArray() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(WithBigArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray), - "::", - stringify!(b) - ) - ); -} -impl Clone for WithBigArray { - fn clone(&self) -> Self { - *self - } -} -impl Default for WithBigArray { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct WithBigArray2 { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField<[::std::os::raw::c_char; 33usize]>, - pub bindgen_union_field: [u32; 9usize], -} -#[test] -fn bindgen_test_layout_WithBigArray2() { - assert_eq!( - ::std::mem::size_of::(), - 36usize, - concat!("Size of: ", stringify!(WithBigArray2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigArray2)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray2), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigArray2), - "::", - stringify!(b) - ) - ); -} -impl Clone for WithBigArray2 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Copy)] -pub struct WithBigMember { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField, - pub bindgen_union_field: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigMember() { - assert_eq!( - ::std::mem::size_of::(), - 132usize, - concat!("Size of: ", stringify!(WithBigMember)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(WithBigMember)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigMember), - "::", - stringify!(a) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).b as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WithBigMember), - "::", - stringify!(b) - ) - ); -} -impl Clone for WithBigMember { - fn clone(&self) -> Self { - *self - } -} -impl Default for WithBigMember { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_nesting.rs b/tests/expectations/tests/union_with_nesting.rs deleted file mode 100644 index 631005f81e..0000000000 --- a/tests/expectations/tests/union_with_nesting.rs +++ /dev/null @@ -1,158 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo { - pub a: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct foo__bindgen_ty_1 { - pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, - pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1__bindgen_ty_1 { - pub b1: ::std::os::raw::c_ushort, - pub b2: ::std::os::raw::c_ushort, - _bindgen_union_align: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).b1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(b1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).b2 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(b2) - ) - ); -} -impl Default for foo__bindgen_ty_1__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union foo__bindgen_ty_1__bindgen_ty_2 { - pub c1: ::std::os::raw::c_ushort, - pub c2: ::std::os::raw::c_ushort, - _bindgen_union_align: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(c1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c2 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(c2) - ) - ); -} -impl Default for foo__bindgen_ty_1__bindgen_ty_2 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); -} -impl Default for foo__bindgen_ty_1 { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/union_with_nesting_1_0.rs b/tests/expectations/tests/union_with_nesting_1_0.rs deleted file mode 100644 index 9c7956ea33..0000000000 --- a/tests/expectations/tests/union_with_nesting_1_0.rs +++ /dev/null @@ -1,201 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) - } -} -impl ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __BindgenUnionField {} -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::std::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::std::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::std::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1 { - pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, - pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_1 { - pub b1: __BindgenUnionField<::std::os::raw::c_ushort>, - pub b2: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).b1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(b1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).b2 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(b2) - ) - ); -} -impl Clone for foo__bindgen_ty_1__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct foo__bindgen_ty_1__bindgen_ty_2 { - pub c1: __BindgenUnionField<::std::os::raw::c_ushort>, - pub c2: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(c1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).c2 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(c2) - ) - ); -} -impl Clone for foo__bindgen_ty_1__bindgen_ty_2 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) - ); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/unknown_attr.rs b/tests/expectations/tests/unknown_attr.rs deleted file mode 100644 index 5040465f88..0000000000 --- a/tests/expectations/tests/unknown_attr.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct max_align_t { - pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, - pub __bindgen_padding_0: u64, - pub __clang_max_align_nonce2: ::std::os::raw::c_longlong, - pub __bindgen_padding_1: u64, -} -#[test] -fn bindgen_test_layout_max_align_t() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(max_align_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__clang_max_align_nonce1 as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(max_align_t), - "::", - stringify!(__clang_max_align_nonce1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__clang_max_align_nonce2 as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(max_align_t), - "::", - stringify!(__clang_max_align_nonce2) - ) - ); -} diff --git a/tests/expectations/tests/use-core.rs b/tests/expectations/tests/use-core.rs deleted file mode 100644 index d4e53ef16e..0000000000 --- a/tests/expectations/tests/use-core.rs +++ /dev/null @@ -1,97 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -extern crate core; - -#[repr(C)] -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct foo { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, - pub bar: *mut ::std::os::raw::c_void, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::core::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::core::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).bar as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Default for foo { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union _bindgen_ty_1 { - pub bar: ::std::os::raw::c_int, - pub baz: ::std::os::raw::c_long, - _bindgen_union_align: u64, -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::core::mem::size_of::<_bindgen_ty_1>(), - 8usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::core::mem::align_of::<_bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::<_bindgen_ty_1>())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(bar) - ) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::<_bindgen_ty_1>())).baz as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(baz) - ) - ); -} -impl Default for _bindgen_ty_1 { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}bazz"] - pub static mut bazz: _bindgen_ty_1; -} -pub type fooFunction = ::core::option::Option; diff --git a/tests/expectations/tests/use-core_1_0.rs b/tests/expectations/tests/use-core_1_0.rs deleted file mode 100644 index 8a867817dd..0000000000 --- a/tests/expectations/tests/use-core_1_0.rs +++ /dev/null @@ -1,145 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -extern crate core; - -#[repr(C)] -pub struct __BindgenUnionField(::core::marker::PhantomData); -impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::core::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::core::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::core::mem::transmute(self) - } -} -impl ::core::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } -} -impl ::core::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::core::marker::Copy for __BindgenUnionField {} -impl ::core::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -impl ::core::hash::Hash for __BindgenUnionField { - fn hash(&self, _state: &mut H) {} -} -impl ::core::cmp::PartialEq for __BindgenUnionField { - fn eq(&self, _other: &__BindgenUnionField) -> bool { - true - } -} -impl ::core::cmp::Eq for __BindgenUnionField {} -#[repr(C)] -#[derive(Debug, Copy, Hash, PartialEq, Eq)] -pub struct foo { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, - pub bar: *mut ::std::os::raw::c_void, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::core::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::core::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(a)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).b as *const _ as usize }, - 4usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(b)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::())).bar as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) - ); -} -impl Clone for foo { - fn clone(&self) -> Self { - *self - } -} -impl Default for foo { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct _bindgen_ty_1 { - pub bar: __BindgenUnionField<::std::os::raw::c_int>, - pub baz: __BindgenUnionField<::std::os::raw::c_long>, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!( - ::core::mem::size_of::<_bindgen_ty_1>(), - 8usize, - concat!("Size of: ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - ::core::mem::align_of::<_bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(_bindgen_ty_1)) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::<_bindgen_ty_1>())).bar as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(bar) - ) - ); - assert_eq!( - unsafe { &(*(::core::ptr::null::<_bindgen_ty_1>())).baz as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_bindgen_ty_1), - "::", - stringify!(baz) - ) - ); -} -impl Clone for _bindgen_ty_1 { - fn clone(&self) -> Self { - *self - } -} -extern "C" { - #[link_name = "\u{1}bazz"] - pub static mut bazz: _bindgen_ty_1; -} -pub type fooFunction = ::core::option::Option; diff --git a/tests/expectations/tests/using.rs b/tests/expectations/tests/using.rs deleted file mode 100644 index 9bc5e303d4..0000000000 --- a/tests/expectations/tests/using.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Point { - pub x: T, - pub y: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for Point { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type IntPoint2D = Point<::std::os::raw::c_int>; -pub type IntVec2D = Point<::std::os::raw::c_int>; diff --git a/tests/expectations/tests/var-tracing.rs b/tests/expectations/tests/var-tracing.rs deleted file mode 100644 index 03b23eadb6..0000000000 --- a/tests/expectations/tests/var-tracing.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub m_baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Bar)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).m_baz as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Bar), - "::", - stringify!(m_baz) - ) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3BarC1Ei"] - pub fn Bar_Bar(this: *mut Bar, baz: ::std::os::raw::c_int); -} -impl Bar { - #[inline] - pub unsafe fn new(baz: ::std::os::raw::c_int) -> Self { - let mut __bindgen_tmp = ::std::mem::uninitialized(); - Bar_Bar(&mut __bindgen_tmp, baz); - __bindgen_tmp - } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Baz { - pub _address: u8, -} -extern "C" { - #[link_name = "\u{1}_ZN3Baz3FOOE"] - pub static mut Baz_FOO: [Bar; 0usize]; -} -#[test] -fn bindgen_test_layout_Baz() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Baz)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Baz)) - ); -} diff --git a/tests/expectations/tests/variadic-method.rs b/tests/expectations/tests/variadic-method.rs deleted file mode 100644 index 94dd73bee0..0000000000 --- a/tests/expectations/tests/variadic-method.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -extern "C" { - #[link_name = "\u{1}_Z3fooPKcz"] - pub fn foo(fmt: *const ::std::os::raw::c_char, ...); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Bar)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Bar)) - ); -} -extern "C" { - #[link_name = "\u{1}_ZN3Bar3fooEPKcz"] - pub fn Bar_foo(this: *mut Bar, fmt: *const ::std::os::raw::c_char, ...); -} diff --git a/tests/expectations/tests/vector.rs b/tests/expectations/tests/vector.rs deleted file mode 100644 index 357b9ef4c6..0000000000 --- a/tests/expectations/tests/vector.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct foo { - pub mMember: [::std::os::raw::c_longlong; 1usize], -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(foo)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mMember as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(foo), - "::", - stringify!(mMember) - ) - ); -} diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs deleted file mode 100644 index 9183090899..0000000000 --- a/tests/expectations/tests/virtual_dtor.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -pub struct nsSlots__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug)] -pub struct nsSlots { - pub vtable_: *const nsSlots__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsSlots() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(nsSlots)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(nsSlots)) - ); -} -impl Default for nsSlots { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN7nsSlotsD1Ev"] - pub fn nsSlots_nsSlots_destructor(this: *mut nsSlots); -} diff --git a/tests/expectations/tests/virtual_inheritance.rs b/tests/expectations/tests/virtual_inheritance.rs deleted file mode 100644 index ed5d115157..0000000000 --- a/tests/expectations/tests/virtual_inheritance.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct A { - pub foo: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(A)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(A)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).foo as *const _ as usize }, - 0usize, - concat!("Offset of field: ", stringify!(A), "::", stringify!(foo)) - ); -} -#[repr(C)] -pub struct B__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct B { - pub vtable_: *const B__bindgen_vtable, - pub bar: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(B)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(B)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).bar as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(B), "::", stringify!(bar)) - ); -} -impl Default for B { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -pub struct C__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct C { - pub vtable_: *const C__bindgen_vtable, - pub baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(C)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).baz as *const _ as usize }, - 8usize, - concat!("Offset of field: ", stringify!(C), "::", stringify!(baz)) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct D { - pub _base: C, - pub _base_1: B, - pub bazz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(D)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(D)) - ); -} -impl Default for D { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/virtual_overloaded.rs b/tests/expectations/tests/virtual_overloaded.rs deleted file mode 100644 index 376bae8a84..0000000000 --- a/tests/expectations/tests/virtual_overloaded.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct C__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct C { - pub vtable_: *const C__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(C)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(C)) - ); -} -impl Default for C { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN1C8do_thingEc"] - pub fn C_do_thing(this: *mut ::std::os::raw::c_void, arg1: ::std::os::raw::c_char); -} -extern "C" { - #[link_name = "\u{1}_ZN1C8do_thingEi"] - pub fn C_do_thing1(this: *mut ::std::os::raw::c_void, arg1: ::std::os::raw::c_int); -} diff --git a/tests/expectations/tests/vtable_recursive_sig.rs b/tests/expectations/tests/vtable_recursive_sig.rs deleted file mode 100644 index f0720f2735..0000000000 --- a/tests/expectations/tests/vtable_recursive_sig.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -pub struct Base__bindgen_vtable(::std::os::raw::c_void); -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Base { - pub vtable_: *const Base__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_Base() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Base)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Base)) - ); -} -impl Default for Base { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -extern "C" { - #[link_name = "\u{1}_ZN4Base9AsDerivedEv"] - pub fn Base_AsDerived(this: *mut ::std::os::raw::c_void) -> *mut Derived; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Derived { - pub _base: Base, -} -#[test] -fn bindgen_test_layout_Derived() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(Derived)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(Derived)) - ); -} -impl Default for Derived { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs deleted file mode 100644 index 8ab2987cf6..0000000000 --- a/tests/expectations/tests/weird_bitfields.rs +++ /dev/null @@ -1,380 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - storage: Storage, - align: [Align; 0], -} - -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn new(storage: Storage) -> Self { - Self { storage, align: [] } - } - - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - byte & mask == mask - } - - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - - let bit_index = index % 8; - let mask = 1 << bit_index; - - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - let mut val = 0; - - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - val |= 1 << i; - } - } - - val - } - - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - self.set_bit(i + bit_offset, val_bit_is_set); - } - } -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum nsStyleSVGOpacitySource { - eStyleSVGOpacitySource_Normal = 0, - eStyleSVGOpacitySource_ContextFillOpacity = 1, - eStyleSVGOpacitySource_ContextStrokeOpacity = 2, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Weird { - pub mStrokeDasharrayLength: ::std::os::raw::c_uint, - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u16>, - pub mClipRule: ::std::os::raw::c_uchar, - pub mColorInterpolation: ::std::os::raw::c_uchar, - pub mColorInterpolationFilters: ::std::os::raw::c_uchar, - pub mFillRule: ::std::os::raw::c_uchar, - pub mImageRendering: ::std::os::raw::c_uchar, - pub mPaintOrder: ::std::os::raw::c_uchar, - pub mShapeRendering: ::std::os::raw::c_uchar, - pub mStrokeLinecap: ::std::os::raw::c_uchar, - pub mStrokeLinejoin: ::std::os::raw::c_uchar, - pub mTextAnchor: ::std::os::raw::c_uchar, - pub mTextRendering: ::std::os::raw::c_uchar, - pub _bitfield_2: __BindgenBitfieldUnit<[u8; 2usize], u8>, - pub __bindgen_padding_0: [u8; 3usize], -} -#[test] -fn bindgen_test_layout_Weird() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(Weird)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(Weird)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mStrokeDasharrayLength as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mStrokeDasharrayLength) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mClipRule as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mClipRule) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mColorInterpolation as *const _ as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mColorInterpolation) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).mColorInterpolationFilters as *const _ as usize - }, - 10usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mColorInterpolationFilters) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mFillRule as *const _ as usize }, - 11usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mFillRule) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mImageRendering as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mImageRendering) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mPaintOrder as *const _ as usize }, - 13usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mPaintOrder) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mShapeRendering as *const _ as usize }, - 14usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mShapeRendering) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mStrokeLinecap as *const _ as usize }, - 15usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mStrokeLinecap) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mStrokeLinejoin as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mStrokeLinejoin) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mTextAnchor as *const _ as usize }, - 17usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mTextAnchor) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).mTextRendering as *const _ as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(Weird), - "::", - stringify!(mTextRendering) - ) - ); -} -impl Default for Weird { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Weird { - #[inline] - pub fn bitTest(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) } - } - #[inline] - pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 16u8, val as u64) - } - } - #[inline] - pub fn bitTest2(&self) -> ::std::os::raw::c_uint { - unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 15u8) as u32) } - } - #[inline] - pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_1.set(16usize, 15u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - bitTest: ::std::os::raw::c_uint, - bitTest2: ::std::os::raw::c_uint, - ) -> __BindgenBitfieldUnit<[u8; 4usize], u16> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u16> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 16u8, { - let bitTest: u32 = unsafe { ::std::mem::transmute(bitTest) }; - bitTest as u64 - }); - __bindgen_bitfield_unit.set(16usize, 15u8, { - let bitTest2: u32 = unsafe { ::std::mem::transmute(bitTest2) }; - bitTest2 as u64 - }); - __bindgen_bitfield_unit - } - #[inline] - pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource { - unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 3u8) as u32) } - } - #[inline] - pub fn set_mFillOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_2.set(0usize, 3u8, val as u64) - } - } - #[inline] - pub fn mStrokeOpacitySource(&self) -> nsStyleSVGOpacitySource { - unsafe { ::std::mem::transmute(self._bitfield_2.get(3usize, 3u8) as u32) } - } - #[inline] - pub fn set_mStrokeOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { - unsafe { - let val: u32 = ::std::mem::transmute(val); - self._bitfield_2.set(3usize, 3u8, val as u64) - } - } - #[inline] - pub fn mStrokeDasharrayFromObject(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_2.get(6usize, 1u8) as u8) } - } - #[inline] - pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_2.set(6usize, 1u8, val as u64) - } - } - #[inline] - pub fn mStrokeDashoffsetFromObject(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_2.get(7usize, 1u8) as u8) } - } - #[inline] - pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_2.set(7usize, 1u8, val as u64) - } - } - #[inline] - pub fn mStrokeWidthFromObject(&self) -> bool { - unsafe { ::std::mem::transmute(self._bitfield_2.get(8usize, 1u8) as u8) } - } - #[inline] - pub fn set_mStrokeWidthFromObject(&mut self, val: bool) { - unsafe { - let val: u8 = ::std::mem::transmute(val); - self._bitfield_2.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_2( - mFillOpacitySource: nsStyleSVGOpacitySource, - mStrokeOpacitySource: nsStyleSVGOpacitySource, - mStrokeDasharrayFromObject: bool, - mStrokeDashoffsetFromObject: bool, - mStrokeWidthFromObject: bool, - ) -> __BindgenBitfieldUnit<[u8; 2usize], u8> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u8> = - Default::default(); - __bindgen_bitfield_unit.set(0usize, 3u8, { - let mFillOpacitySource: u32 = unsafe { ::std::mem::transmute(mFillOpacitySource) }; - mFillOpacitySource as u64 - }); - __bindgen_bitfield_unit.set(3usize, 3u8, { - let mStrokeOpacitySource: u32 = unsafe { ::std::mem::transmute(mStrokeOpacitySource) }; - mStrokeOpacitySource as u64 - }); - __bindgen_bitfield_unit.set(6usize, 1u8, { - let mStrokeDasharrayFromObject: u8 = - unsafe { ::std::mem::transmute(mStrokeDasharrayFromObject) }; - mStrokeDasharrayFromObject as u64 - }); - __bindgen_bitfield_unit.set(7usize, 1u8, { - let mStrokeDashoffsetFromObject: u8 = - unsafe { ::std::mem::transmute(mStrokeDashoffsetFromObject) }; - mStrokeDashoffsetFromObject as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let mStrokeWidthFromObject: u8 = - unsafe { ::std::mem::transmute(mStrokeWidthFromObject) }; - mStrokeWidthFromObject as u64 - }); - __bindgen_bitfield_unit - } -} diff --git a/tests/expectations/tests/what_is_going_on.rs b/tests/expectations/tests/what_is_going_on.rs deleted file mode 100644 index d0e4c689c7..0000000000 --- a/tests/expectations/tests/what_is_going_on.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct UnknownUnits { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_UnknownUnits() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(UnknownUnits)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(UnknownUnits)) - ); -} -pub type Float = f32; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct PointTyped { - pub x: F, - pub y: F, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for PointTyped { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -pub type IntPoint = PointTyped; diff --git a/tests/expectations/tests/whitelist-namespaces-basic.rs b/tests/expectations/tests/whitelist-namespaces-basic.rs deleted file mode 100644 index 74c782f77c..0000000000 --- a/tests/expectations/tests/whitelist-namespaces-basic.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod outer { - #[allow(unused_imports)] - use self::super::super::root; - pub mod inner { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Helper { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Helper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Helper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Helper)) - ); - } - } - } -} diff --git a/tests/expectations/tests/whitelist-namespaces.rs b/tests/expectations/tests/whitelist-namespaces.rs deleted file mode 100644 index cd179ca74c..0000000000 --- a/tests/expectations/tests/whitelist-namespaces.rs +++ /dev/null @@ -1,65 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] -pub mod root { - #[allow(unused_imports)] - use self::super::root; - pub mod outer { - #[allow(unused_imports)] - use self::super::super::root; - pub mod inner { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Helper { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_Helper() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Helper)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Helper)) - ); - } - } - #[repr(C)] - #[derive(Debug, Default, Copy, Clone)] - pub struct Test { - pub helper: root::outer::inner::Helper, - } - #[test] - fn bindgen_test_layout_Test() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Test)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Test)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).helper as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(Test), - "::", - stringify!(helper) - ) - ); - } - } -} diff --git a/tests/expectations/tests/whitelist_basic.rs b/tests/expectations/tests/whitelist_basic.rs deleted file mode 100644 index 7ff1160dad..0000000000 --- a/tests/expectations/tests/whitelist_basic.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct WhitelistMe { - pub foo: ::std::os::raw::c_int, - pub bar: WhitelistMe_Inner, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct WhitelistMe_Inner { - pub bar: T, - pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, -} -impl Default for WhitelistMe_Inner { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} -impl Default for WhitelistMe { - fn default() -> Self { - unsafe { ::std::mem::zeroed() } - } -} diff --git a/tests/expectations/tests/whitelist_fix.rs b/tests/expectations/tests/whitelist_fix.rs deleted file mode 100644 index ed30347cc0..0000000000 --- a/tests/expectations/tests/whitelist_fix.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub enum Test {} - -extern "C" { - pub fn Servo_Test(a: *mut Test); -} diff --git a/tests/expectations/tests/whitelist_vars.rs b/tests/expectations/tests/whitelist_vars.rs deleted file mode 100644 index b8f1099825..0000000000 --- a/tests/expectations/tests/whitelist_vars.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - -pub const NONE: u32 = 0; -pub const FOO: u32 = 5; -pub const FOOB: i32 = -2; -pub const FOOBAR: i32 = -10; diff --git a/tests/expectations/tests/whitelisted-item-references-no-hash.rs b/tests/expectations/tests/whitelisted-item-references-no-hash.rs deleted file mode 100644 index bf6eda64ed..0000000000 --- a/tests/expectations/tests/whitelisted-item-references-no-hash.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoHash { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_NoHash() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(NoHash)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(NoHash)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct WhitelistMe { - pub a: NoHash, -} -#[test] -fn bindgen_test_layout_WhitelistMe() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(WhitelistMe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(WhitelistMe)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WhitelistMe), - "::", - stringify!(a) - ) - ); -} diff --git a/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs b/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs deleted file mode 100644 index cfcbf5a458..0000000000 --- a/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct NoPartialEq { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_NoPartialEq() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(NoPartialEq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(NoPartialEq)) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct WhitelistMe { - pub a: NoPartialEq, -} -#[test] -fn bindgen_test_layout_WhitelistMe() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(WhitelistMe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(WhitelistMe)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WhitelistMe), - "::", - stringify!(a) - ) - ); -} diff --git a/tests/expectations/tests/whitelisted_item_references_no_copy.rs b/tests/expectations/tests/whitelisted_item_references_no_copy.rs deleted file mode 100644 index 2e635dc2c8..0000000000 --- a/tests/expectations/tests/whitelisted_item_references_no_copy.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default)] -pub struct NoCopy { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_NoCopy() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(NoCopy)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(NoCopy)) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct WhitelistMe { - pub a: NoCopy, -} -#[test] -fn bindgen_test_layout_WhitelistMe() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(WhitelistMe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(WhitelistMe)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).a as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(WhitelistMe), - "::", - stringify!(a) - ) - ); -} diff --git a/tests/expectations/tests/win32-thiscall_1_0.rs b/tests/expectations/tests/win32-thiscall_1_0.rs deleted file mode 100644 index f84a70055b..0000000000 --- a/tests/expectations/tests/win32-thiscall_1_0.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Debug, Default, Copy)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -impl Clone for Foo { - fn clone(&self) -> Self { - *self - } -} diff --git a/tests/expectations/tests/win32-thiscall_nightly.rs b/tests/expectations/tests/win32-thiscall_nightly.rs deleted file mode 100644 index 3b0140dcbf..0000000000 --- a/tests/expectations/tests/win32-thiscall_nightly.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#![cfg(feature = "nightly")] -#![feature(abi_thiscall)] - -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct Foo { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(Foo)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(Foo)) - ); -} -extern "thiscall" { - #[link_name = "\u{1}?test@Foo@@QAEXXZ"] - pub fn Foo_test(this: *mut Foo); -} -extern "thiscall" { - #[link_name = "\u{1}?test2@Foo@@QAEHH@Z"] - pub fn Foo_test2(this: *mut Foo, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -impl Foo { - #[inline] - pub unsafe fn test(&mut self) { - Foo_test(self) - } - #[inline] - pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int { - Foo_test2(self, var) - } -} diff --git a/tests/expectations/tests/zero-sized-array.rs b/tests/expectations/tests/zero-sized-array.rs deleted file mode 100644 index fe78ae86ce..0000000000 --- a/tests/expectations/tests/zero-sized-array.rs +++ /dev/null @@ -1,159 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData); -impl __IncompleteArrayField { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl ::std::clone::Clone for __IncompleteArrayField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl ::std::marker::Copy for __IncompleteArrayField {} -/// Bizarrely enough, this should *not* get an `_address` field. -#[repr(C)] -#[derive(Debug, Default)] -pub struct ZeroSizedArray { - pub arr: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_ZeroSizedArray() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(ZeroSizedArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ZeroSizedArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).arr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ZeroSizedArray), - "::", - stringify!(arr) - ) - ); -} -/// And nor should this get an `_address` field. -#[repr(C)] -#[derive(Debug, Default)] -pub struct ContainsZeroSizedArray { - pub zsa: ZeroSizedArray, -} -#[test] -fn bindgen_test_layout_ContainsZeroSizedArray() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(ContainsZeroSizedArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ContainsZeroSizedArray)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).zsa as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ContainsZeroSizedArray), - "::", - stringify!(zsa) - ) - ); -} -/// Inheriting from ZeroSizedArray shouldn't cause an `_address` to be inserted -/// either. -#[repr(C)] -#[derive(Debug, Default)] -pub struct InheritsZeroSizedArray { - pub _base: ZeroSizedArray, -} -#[test] -fn bindgen_test_layout_InheritsZeroSizedArray() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(InheritsZeroSizedArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(InheritsZeroSizedArray)) - ); -} -/// And this should not get an `_address` field either. -#[repr(C, packed)] -#[derive(Debug, Default)] -pub struct DynamicallySizedArray { - pub arr: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_DynamicallySizedArray() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(DynamicallySizedArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(DynamicallySizedArray)) - ); -} -/// No `_address` field here either. -#[repr(C)] -#[derive(Debug, Default)] -pub struct ContainsDynamicallySizedArray { - pub dsa: DynamicallySizedArray, -} -#[test] -fn bindgen_test_layout_ContainsDynamicallySizedArray() { - assert_eq!( - ::std::mem::size_of::(), - 0usize, - concat!("Size of: ", stringify!(ContainsDynamicallySizedArray)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ContainsDynamicallySizedArray)) - ); -} diff --git a/tests/headers/16-byte-alignment_1_0.h b/tests/headers/16-byte-alignment_1_0.h deleted file mode 100644 index 8a9fd4910e..0000000000 --- a/tests/headers/16-byte-alignment_1_0.h +++ /dev/null @@ -1,34 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -struct rte_ipv4_tuple { - uint32_t src_addr; - uint32_t dst_addr; - union { - struct { - uint16_t dport; - uint16_t sport; - }; - uint32_t sctp_tag; - }; -}; - -struct rte_ipv6_tuple { - uint8_t src_addr[16]; - uint8_t dst_addr[16]; - union { - struct { - uint16_t dport; - uint16_t sport; - }; - uint32_t sctp_tag; - }; -}; - -union rte_thash_tuple { - struct rte_ipv4_tuple v4; - struct rte_ipv6_tuple v6; -} __attribute__((aligned(16))); diff --git a/tests/headers/anon_enum_whitelist.h b/tests/headers/anon_enum_whitelist.h deleted file mode 100644 index fc4810e044..0000000000 --- a/tests/headers/anon_enum_whitelist.h +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --whitelist-var NODE_.* --rustified-enum .* - -enum { - NODE_FLAG_FOO, - NODE_FLAG_BAR, -}; diff --git a/tests/headers/anon_struct_in_union_1_0.h b/tests/headers/anon_struct_in_union_1_0.h deleted file mode 100644 index 6b59723a3c..0000000000 --- a/tests/headers/anon_struct_in_union_1_0.h +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct s { - union { - struct inner { - int b; - } field; - } u; -}; diff --git a/tests/headers/anon_union_1_0.hpp b/tests/headers/anon_union_1_0.hpp deleted file mode 100644 index 314215bfe5..0000000000 --- a/tests/headers/anon_union_1_0.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* - -template -struct TErrorResult { - enum UnionState { - HasMessage, - HasException, - }; - int mResult; - struct Message; - struct DOMExceptionInfo; - union { - Message* mMessage; - DOMExceptionInfo* mDOMExceptionInfo; - }; - - bool mMightHaveUnreported; - UnionState mUnionState; -}; - -struct ErrorResult : public TErrorResult { -}; diff --git a/tests/headers/bitfield_align_2.h b/tests/headers/bitfield_align_2.h deleted file mode 100644 index 31d37f76a7..0000000000 --- a/tests/headers/bitfield_align_2.h +++ /dev/null @@ -1,12 +0,0 @@ -// bindgen-flags: --rustified-enum .* -enum MyEnum { - ONE, - TWO, - THREE, - FOUR -}; - -struct TaggedPtr { - enum MyEnum tag : 2; - long ptr : 62; -}; diff --git a/tests/headers/blacklist-and-impl-debug.hpp b/tests/headers/blacklist-and-impl-debug.hpp deleted file mode 100644 index b4b39fe40d..0000000000 --- a/tests/headers/blacklist-and-impl-debug.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --impl-debug --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' - -struct BlacklistMe {}; - -/** - * Because this type contains a blacklisted type, it should not derive Debug. - */ -struct ShouldManuallyImplDebug { - BlacklistMe a; -}; diff --git a/tests/headers/blocks.h b/tests/headers/blocks.h deleted file mode 100644 index 80420e6e45..0000000000 --- a/tests/headers/blocks.h +++ /dev/null @@ -1,3 +0,0 @@ -// bindgen-flags: -- -fblocks - -void atexit_b(void (^)(void)); diff --git a/tests/headers/class_1_0.hpp b/tests/headers/class_1_0.hpp deleted file mode 100644 index e3735eb68d..0000000000 --- a/tests/headers/class_1_0.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --impl-partialeq --with-derive-eq - -class C { - int a; - // More than rust limits (32) - char big_array[33]; -}; - -class C_with_zero_length_array { - int a; - // More than rust limits (32) - char big_array[33]; - char zero_length_array[0]; -}; - -class C_with_zero_length_array_2 { - int a; - char zero_length_array[0]; -}; - -class C_with_incomplete_array { - int a; - // More than rust limits (32) - char big_array[33]; - char incomplete_array[]; -}; - -class C_with_incomplete_array_2 { - int a; - char incomplete_array[]; -}; - - -class C_with_zero_length_array_and_incomplete_array { - int a; - // More than rust limits (32) - char big_array[33]; - char zero_length_array[0]; - char incomplete_array[]; -}; - -class C_with_zero_length_array_and_incomplete_array_2 { - int a; - char zero_length_array[0]; - char incomplete_array[]; -}; - - -class WithDtor { - int b; - - ~WithDtor() {} -}; - -class IncompleteArrayNonCopiable { - void* whatever; - C incomplete_array[]; -}; - -union Union { - float d; - int i; -}; - -class WithUnion { - Union data; -}; - -class RealAbstractionWithTonsOfMethods { - void foo(); -public: - void bar() const; - void bar(); - void bar(int foo); - static void sta(); -}; diff --git a/tests/headers/class_with_inner_struct_1_0.hpp b/tests/headers/class_with_inner_struct_1_0.hpp deleted file mode 100644 index 1bae249f8a..0000000000 --- a/tests/headers/class_with_inner_struct_1_0.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* -// bindgen-flags: -- -std=c++11 - -class A { - unsigned c; - struct Segment { int begin, end; }; - union { - int f; - } named_union; - union { - int d; - }; -}; - -class B { - unsigned d; - struct Segment { int begin, end; }; -}; - - -enum class StepSyntax { - Keyword, // step-start and step-end - FunctionalWithoutKeyword, // steps(...) - FunctionalWithStartKeyword, // steps(..., start) - FunctionalWithEndKeyword, // steps(..., end) -}; - -class C { - unsigned d; - union { - struct { - float mX1; - float mY1; - float mX2; - float mY2; - } mFunc; - struct { - StepSyntax mStepSyntax; - unsigned int mSteps; - }; - }; - // To ensure it doesn't collide - struct Segment { int begin, end; }; -}; diff --git a/tests/headers/const_enum_unnamed.hpp b/tests/headers/const_enum_unnamed.hpp deleted file mode 100644 index bdd9700f87..0000000000 --- a/tests/headers/const_enum_unnamed.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --rustified-enum .* - -enum { - FOO_BAR, - FOO_BAZ, -}; - -class Foo { - enum { FOO_BAR = 10 }; -}; diff --git a/tests/headers/derive-clone_1_0.h b/tests/headers/derive-clone_1_0.h deleted file mode 100644 index 34ef40ae97..0000000000 --- a/tests/headers/derive-clone_1_0.h +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rust-target 1.0 - -/// Since builtin `Clone` impls were introduced in Rust 1.21 this struct -/// should impl `Clone` "manually". -struct ShouldImplClone { - int large[33]; -}; diff --git a/tests/headers/derive-default-and-blacklist.hpp b/tests/headers/derive-default-and-blacklist.hpp deleted file mode 100644 index 7a2b7505d5..0000000000 --- a/tests/headers/derive-default-and-blacklist.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// bindgen-flags: --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' - -// Note that we do not explicitly provide the `--with-derive-default` flag -// above, since it is added by the test runner implicitly. - -struct BlacklistMe {}; - -/** - * Because this type contains a blacklisted type, it should not derive - * Default. Instead, we should emit a `mem::zeroed` implementation. - */ -struct ShouldNotDeriveDefault { - BlacklistMe a; -}; diff --git a/tests/headers/derive-hash-and-blacklist.hpp b/tests/headers/derive-hash-and-blacklist.hpp deleted file mode 100644 index 4b3a4a535b..0000000000 --- a/tests/headers/derive-hash-and-blacklist.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --with-derive-hash --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' - -struct BlacklistMe {}; - -/** - * Because this type contains a blacklisted type, it should not derive Hash. - */ -struct ShouldNotDeriveHash { - BlacklistMe a; -}; diff --git a/tests/headers/derive-hash-blacklisting.hpp b/tests/headers/derive-hash-blacklisting.hpp deleted file mode 100644 index e3256a0118..0000000000 --- a/tests/headers/derive-hash-blacklisting.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-ord --with-derive-partialeq --with-derive-eq --whitelist-type 'Whitelisted.*' --blacklist-type Blacklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blacklisted {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell> }" -// -template -struct Blacklisted { - T t; -}; - -/// This would derive(Hash, Eq, PartialEq) if it didn't contain a blacklisted type, -/// causing us to conservatively avoid deriving hash/Eq/PartialEq for it. -struct WhitelistedOne { - Blacklisted a; -}; - -/// This can't derive(Hash/Eq) even if it didn't contain a blacklisted type. -struct WhitelistedTwo { - Blacklisted b; -}; diff --git a/tests/headers/derive-partialeq-and-blacklist.hpp b/tests/headers/derive-partialeq-and-blacklist.hpp deleted file mode 100644 index a996eee873..0000000000 --- a/tests/headers/derive-partialeq-and-blacklist.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --with-derive-partialeq --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' - -struct BlacklistMe {}; - -/** - * Because this type contains a blacklisted type, it should not derive - * PartialEq. - */ -struct ShouldNotDerivePartialEq { - BlacklistMe a; -}; diff --git a/tests/headers/derive-partialeq-union_1_0.hpp b/tests/headers/derive-partialeq-union_1_0.hpp deleted file mode 100644 index d546d77b10..0000000000 --- a/tests/headers/derive-partialeq-union_1_0.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-partialeq --impl-partialeq - -/// This should manually derive PartialEq. -union ShouldDerivePartialEq { - char a[150]; - int b; -}; diff --git a/tests/headers/divide-by-zero-in-struct-layout.h b/tests/headers/divide-by-zero-in-struct-layout.h deleted file mode 100644 index 470250d3b7..0000000000 --- a/tests/headers/divide-by-zero-in-struct-layout.h +++ /dev/null @@ -1,22 +0,0 @@ -// bindgen-flags: --no-layout-tests -// -// Unfortunately, we aren't translating the second and third structs correctly -// yet. But we definitely shouldn't divide-by-zero when we see it... -// -// Once we fix #981 we should remove the `--no-layout-tests`. - -struct WithBitfield { - unsigned : 7; - unsigned a; -}; - -struct WithBitfieldAndAttrPacked { - unsigned : 7; - unsigned a; -} __attribute__((packed)); - -#pragma pack(1) -struct WithBitfieldAndPacked { - unsigned : 7; - unsigned a; -}; diff --git a/tests/headers/enum-doc.h b/tests/headers/enum-doc.h deleted file mode 100644 index 58e2c69e13..0000000000 --- a/tests/headers/enum-doc.h +++ /dev/null @@ -1,18 +0,0 @@ -/** Document enum */ -enum B { - /// Document field with three slashes - VAR_A = 0, - /** Document field with preceeding star */ - VAR_B = 1, - /*! Document field with preceeding exclamation */ - VAR_C = 2, - VAR_D = 3, /**< Document field with following star */ - VAR_E = 4, /*!< Document field with following exclamation */ - /** - * Document field with preceeding star, with a loong long multiline - * comment. - * - * Very interesting documentation, definitely. - */ - VAR_F, -}; diff --git a/tests/headers/enum.h b/tests/headers/enum.h deleted file mode 100644 index 38ce4eee44..0000000000 --- a/tests/headers/enum.h +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --rustified-enum .* - -enum Foo { - Bar = 0, - Qux -}; - -enum Neg { - MinusOne = -1, - One = 1, -}; diff --git a/tests/headers/enum_alias.hpp b/tests/headers/enum_alias.hpp deleted file mode 100644 index c3ecc35159..0000000000 --- a/tests/headers/enum_alias.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 - -typedef unsigned char uint8_t; - -enum Bar : uint8_t { - VAL -}; diff --git a/tests/headers/enum_and_vtable_mangling.hpp b/tests/headers/enum_and_vtable_mangling.hpp deleted file mode 100644 index e332fc57e6..0000000000 --- a/tests/headers/enum_and_vtable_mangling.hpp +++ /dev/null @@ -1,12 +0,0 @@ -// bindgen-flags: --rustified-enum .* - -enum { - match, - whatever_else, -}; - -class C { - int i; -public: - virtual void match(); -}; diff --git a/tests/headers/enum_dupe.h b/tests/headers/enum_dupe.h deleted file mode 100644 index 826568fb0d..0000000000 --- a/tests/headers/enum_dupe.h +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --rustified-enum .* - -enum Foo { - Bar = 1, - Dupe = 1 -}; diff --git a/tests/headers/enum_explicit_type.hpp b/tests/headers/enum_explicit_type.hpp deleted file mode 100644 index 3cb931386f..0000000000 --- a/tests/headers/enum_explicit_type.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 - -enum Foo: unsigned char { - Bar = 0, - Qux -}; - -enum Neg: signed char { - MinusOne = -1, - One = 1, -}; - -enum Bigger: unsigned short { - Much = 255, - Larger -}; - -enum MuchLong: long { - MuchLow = -4294967296, -}; - -enum MuchLongLong: long long { - I64_MIN = 1ll << 63, -}; - -enum MuchULongLong: unsigned long long { - MuchHigh = 4294967296, -}; - -enum BoolEnumsAreFun: bool { - Value = true, -}; diff --git a/tests/headers/enum_explicit_type_constants.hpp b/tests/headers/enum_explicit_type_constants.hpp deleted file mode 100644 index 7deab3699a..0000000000 --- a/tests/headers/enum_explicit_type_constants.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: -- -std=c++11 -// -// This test is much like enum_explicit_type, but without --rustified-enum. - -#include "enum_explicit_type.hpp" diff --git a/tests/headers/enum_negative.h b/tests/headers/enum_negative.h deleted file mode 100644 index 267f799f02..0000000000 --- a/tests/headers/enum_negative.h +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --rustified-enum .* - -enum Foo { - Bar = -2, - Qux = 1, -}; diff --git a/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h b/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h deleted file mode 100644 index c9189952bb..0000000000 --- a/tests/headers/error-E0600-cannot-apply-unary-negation-to-u32.h +++ /dev/null @@ -1,3 +0,0 @@ -typedef unsigned int uint32_t; - -uint32_t a = 18446744073709551611; diff --git a/tests/headers/forward-enum-decl.hpp b/tests/headers/forward-enum-decl.hpp deleted file mode 100644 index a3df858428..0000000000 --- a/tests/headers/forward-enum-decl.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 - -enum class CSSPseudoClassType : int; - -enum class CSSPseudoClassType : int { - empty, - link, -}; diff --git a/tests/headers/forward_declared_complex_types_1_0.hpp b/tests/headers/forward_declared_complex_types_1_0.hpp deleted file mode 100644 index ff6076fc43..0000000000 --- a/tests/headers/forward_declared_complex_types_1_0.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// bindgen-flags: --rust-target 1.0 - -struct Foo_empty {}; -struct Foo; - -struct Bar { - Foo *f; -}; - -void baz_struct(Foo* f); - -union Union; - -void baz_union(Union* u); - -class Quux; - -void baz_class(Quux* q); diff --git a/tests/headers/func_with_func_ptr_arg.h b/tests/headers/func_with_func_ptr_arg.h deleted file mode 100644 index 629c84ab90..0000000000 --- a/tests/headers/func_with_func_ptr_arg.h +++ /dev/null @@ -1 +0,0 @@ -void foo(void (*bar)()); diff --git a/tests/headers/infinite-macro.h b/tests/headers/infinite-macro.h deleted file mode 100644 index ab352c5785..0000000000 --- a/tests/headers/infinite-macro.h +++ /dev/null @@ -1,2 +0,0 @@ -#define INFINITY (1.0f/0.0f) -#define NAN (0.0f/0.0f) diff --git a/tests/headers/inline_namespace_whitelist.hpp b/tests/headers/inline_namespace_whitelist.hpp deleted file mode 100644 index 30047bbec1..0000000000 --- a/tests/headers/inline_namespace_whitelist.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type=std::string -- -std=c++11 - -namespace std { - inline namespace bar { - using string = const char*; - }; -}; diff --git a/tests/headers/issue-1285.h b/tests/headers/issue-1285.h deleted file mode 100644 index 7fb742ecf7..0000000000 --- a/tests/headers/issue-1285.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --with-derive-hash --no-recursive-whitelist --whitelist-type "foo" - -struct foo { - union { - unsigned int a; - unsigned short b; - } bar; -}; \ No newline at end of file diff --git a/tests/headers/issue-410.hpp b/tests/headers/issue-410.hpp deleted file mode 100644 index c91c83d119..0000000000 --- a/tests/headers/issue-410.hpp +++ /dev/null @@ -1,12 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type JS::Value --rustified-enum .* - -namespace JS { -class Value; -} -typedef enum {} JSWhyMagic; -namespace JS { -class Value { -public: - void a(JSWhyMagic); -}; -} diff --git a/tests/headers/issue-493_1_0.hpp b/tests/headers/issue-493_1_0.hpp deleted file mode 100644 index 7406d8936c..0000000000 --- a/tests/headers/issue-493_1_0.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* - -template -class basic_string -{ -public: - typedef unsigned long long size_type; - typedef char value_type; - typedef value_type * pointer; - - struct __long - { - size_type __cap_; - size_type __size_; - pointer __data_; - }; - - enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? - (sizeof(__long) - 1)/sizeof(value_type) : 2}; - - struct __short - { - union - { - unsigned char __size_; - value_type __lx; - }; - value_type __data_[__min_cap]; - }; - - union __ulx{__long __lx; __short __lxx;}; - - enum {__n_words = sizeof(__ulx) / sizeof(size_type)}; - - struct __raw - { - size_type __words[__n_words]; - }; - - struct __rep - { - union - { - __long __l; - __short __s; - __raw __r; - }; - }; -}; diff --git a/tests/headers/issue-544-stylo-creduce-2.hpp b/tests/headers/issue-544-stylo-creduce-2.hpp deleted file mode 100644 index f3467f4528..0000000000 --- a/tests/headers/issue-544-stylo-creduce-2.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: -- -std=c++14 - -template -struct Foo { - template using FirstAlias = typename T::Associated; - template using SecondAlias = Foo>; - SecondAlias member; -}; diff --git a/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp b/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp deleted file mode 100644 index f817f34dce..0000000000 --- a/tests/headers/issue-645-cannot-find-type-T-in-this-scope.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --blacklist-type RefPtr --raw-line "#[derive(Clone, Copy, Debug)] pub struct RefPtr(T);" --whitelist-type "HasRefPtr" -- -std=c++14 - -template class RefPtr {}; - -template -class HasRefPtr { - typedef T TypedefOfT; - RefPtr refptr_member; -}; diff --git a/tests/headers/issue-648-derive-debug-with-padding.h b/tests/headers/issue-648-derive-debug-with-padding.h deleted file mode 100644 index f528c10011..0000000000 --- a/tests/headers/issue-648-derive-debug-with-padding.h +++ /dev/null @@ -1,23 +0,0 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq -/** - * We emit a `[u8; 63usize]` padding field for this struct, which cannot derive - * Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end - * up with the reight alignment, we're waiting on `#[repr(align="N")]` to land - * in rustc). - */ -struct NoDebug { - char c; - // padding of 63 bytes -} __attribute__((__aligned__(64))); - -/** - * This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive - * Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because - * we determine Debug derive-ability before we compute padding, which happens at - * codegen. (Again, we expect to get the alignment wrong for similar reasons.) - */ -struct ShouldDeriveDebugButDoesNot { - char c[32]; - char d; - // padding of 31 bytes -} __attribute__((__aligned__(64))); diff --git a/tests/headers/issue-662-part-2.hpp b/tests/headers/issue-662-part-2.hpp deleted file mode 100644 index 84edb39778..0000000000 --- a/tests/headers/issue-662-part-2.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --blacklist-type RefPtr --raw-line '#[derive(Clone, Copy, Debug)] pub struct RefPtr(T);' -- --std=c++14 - -// This is pretty much the same as the other issue 662 test case, but this time -// we blacklist RefPtr to exercise the instantiation-of-a-blacklisted-template -// path in the template analysis. - -template class RefPtr {}; -template class nsMainThreadPtrHolder { T a; }; -template class nsMainThreadPtrHandle { - RefPtr> mPtr; -}; diff --git a/tests/headers/issue-674-1.hpp b/tests/headers/issue-674-1.hpp deleted file mode 100644 index f5c0591750..0000000000 --- a/tests/headers/issue-674-1.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type CapturingContentInfo --opaque-type 'mozilla::Maybe' -- -- -std=c++14 - -namespace mozilla { -template class Maybe { using ValueType = T; }; -} -struct CapturingContentInfo { - mozilla::Maybe a; -}; diff --git a/tests/headers/issue-674-2.hpp b/tests/headers/issue-674-2.hpp deleted file mode 100644 index 5f65a05bdc..0000000000 --- a/tests/headers/issue-674-2.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type StaticRefPtr --opaque-type 'JS::Rooted' -- -- -std=c++14 - -namespace JS { -template class Rooted { using ElementType = T; }; -} -class c { - JS::Rooted b; -}; -class B { - c a; -}; -template class StaticRefPtr {}; -struct { - StaticRefPtr d; -} e; diff --git a/tests/headers/issue-674-3.hpp b/tests/headers/issue-674-3.hpp deleted file mode 100644 index c1bd2f32db..0000000000 --- a/tests/headers/issue-674-3.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type nsCSSValue --opaque-type 'nsRefPtrHashtable' -- -- -std=c++14 - -template class nsRefPtrHashtable { - typedef PtrType *UserDataType; -}; -struct a { - nsRefPtrHashtable b; -}; -class nsCSSValue { - a c; -}; diff --git a/tests/headers/issue-769-bad-instantiation-test.hpp b/tests/headers/issue-769-bad-instantiation-test.hpp deleted file mode 100644 index 1be89a6628..0000000000 --- a/tests/headers/issue-769-bad-instantiation-test.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type Rooted - -template -class Rooted { - T member; -}; - -class AutoValueVector : Rooted { - using Alias = int; - using RootedAlias = Rooted; -}; diff --git a/tests/headers/issue-801-opaque-sloppiness.hpp b/tests/headers/issue-801-opaque-sloppiness.hpp deleted file mode 100644 index 678586342e..0000000000 --- a/tests/headers/issue-801-opaque-sloppiness.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --opaque-type "B" --whitelist-type "C" --with-derive-hash --with-derive-partialeq --with-derive-eq - -class A; - -class B { - static A a; -}; - -class C { - B b; -}; diff --git a/tests/headers/issue-833-1.hpp b/tests/headers/issue-833-1.hpp deleted file mode 100644 index 30bf85f2d0..0000000000 --- a/tests/headers/issue-833-1.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --generate functions --whitelist-function func --raw-line "#[repr(C)] pub struct nsTArray { pub hdr: *const () }" - -template -class nsTArray { - static T* sFoo; -}; - -extern "C" nsTArray* func(); diff --git a/tests/headers/issue-833.hpp b/tests/headers/issue-833.hpp deleted file mode 100644 index ea0d2add71..0000000000 --- a/tests/headers/issue-833.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --generate functions --whitelist-function func --raw-line "#[repr(C)] pub struct nsTArray { pub hdr: *const T }" - -template -class nsTArray { - T* mHeader; -}; - -extern "C" nsTArray* func(); diff --git a/tests/headers/issue-834.hpp b/tests/headers/issue-834.hpp deleted file mode 100644 index c06e89fdb4..0000000000 --- a/tests/headers/issue-834.hpp +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --whitelist-type U --generate types - -struct T {}; -struct U { - void test(T a); -}; diff --git a/tests/headers/issue-888-enum-var-decl-jump.hpp b/tests/headers/issue-888-enum-var-decl-jump.hpp deleted file mode 100644 index d7182c3c57..0000000000 --- a/tests/headers/issue-888-enum-var-decl-jump.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --rustified-enum .* - -namespace Halide { -struct Type; -} -typedef enum {} a; -namespace Halide { -struct Type { - static a b; -}; -} diff --git a/tests/headers/issue-944-derive-copy-and-blacklisting.hpp b/tests/headers/issue-944-derive-copy-and-blacklisting.hpp deleted file mode 100644 index 657e0d849f..0000000000 --- a/tests/headers/issue-944-derive-copy-and-blacklisting.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' - -struct BlacklistMe {}; - -/** - * Because this type contains a blacklisted type, it should not derive Copy. - */ -struct ShouldNotBeCopy { - BlacklistMe a; -}; diff --git a/tests/headers/jsval_layout_opaque_1_0.hpp b/tests/headers/jsval_layout_opaque_1_0.hpp deleted file mode 100644 index dcf6274dfb..0000000000 --- a/tests/headers/jsval_layout_opaque_1_0.hpp +++ /dev/null @@ -1,425 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* -// bindgen-flags: -- -std=c++11 - -/** - * These typedefs are hacky, but keep our tests consistent across 64-bit - * platforms, otherwise the id's change and our CI is unhappy. - */ -typedef unsigned char uint8_t; -typedef int int32_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef unsigned long long size_t; -typedef unsigned long long uintptr_t; - - -#define JS_PUNBOX64 -#define IS_LITTLE_ENDIAN - -/* - * Try to get jsvals 64-bit aligned. We could almost assert that all values are - * aligned, but MSVC and GCC occasionally break alignment. - */ -#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__) -# define JSVAL_ALIGNMENT __attribute__((aligned (8))) -#elif defined(_MSC_VER) - /* - * Structs can be aligned with MSVC, but not if they are used as parameters, - * so we just don't try to align. - */ -# define JSVAL_ALIGNMENT -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# define JSVAL_ALIGNMENT -#elif defined(__HP_cc) || defined(__HP_aCC) -# define JSVAL_ALIGNMENT -#endif - -#if defined(JS_PUNBOX64) -# define JSVAL_TAG_SHIFT 47 -#endif - -/* - * We try to use enums so that printing a jsval_layout in the debugger shows - * nice symbolic type tags, however we can only do this when we can force the - * underlying type of the enum to be the desired size. - */ -#if !defined(__SUNPRO_CC) && !defined(__xlC__) - -#if defined(_MSC_VER) -# define JS_ENUM_HEADER(id, type) enum id : type -# define JS_ENUM_FOOTER(id) -#else -# define JS_ENUM_HEADER(id, type) enum id -# define JS_ENUM_FOOTER(id) __attribute__((packed)) -#endif - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueType, uint8_t) -{ - JSVAL_TYPE_DOUBLE = 0x00, - JSVAL_TYPE_INT32 = 0x01, - JSVAL_TYPE_UNDEFINED = 0x02, - JSVAL_TYPE_BOOLEAN = 0x03, - JSVAL_TYPE_MAGIC = 0x04, - JSVAL_TYPE_STRING = 0x05, - JSVAL_TYPE_SYMBOL = 0x06, - JSVAL_TYPE_NULL = 0x07, - JSVAL_TYPE_OBJECT = 0x08, - - /* These never appear in a jsval; they are only provided as an out-of-band value. */ - JSVAL_TYPE_UNKNOWN = 0x20, - JSVAL_TYPE_MISSING = 0x21 -} JS_ENUM_FOOTER(JSValueType); - -static_assert(sizeof(JSValueType) == 1, - "compiler typed enum support is apparently buggy"); - -#if defined(JS_NUNBOX32) - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueTag, uint32_t) -{ - JSVAL_TAG_CLEAR = 0xFFFFFF80, - JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32, - JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED, - JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING, - JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, - JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN, - JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC, - JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL, - JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT -} JS_ENUM_FOOTER(JSValueTag); - -static_assert(sizeof(JSValueTag) == sizeof(uint32_t), - "compiler typed enum support is apparently buggy"); - -#elif defined(JS_PUNBOX64) - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueTag, uint32_t) -{ - JSVAL_TAG_MAX_DOUBLE = 0x1FFF0, - JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32, - JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED, - JSVAL_TAG_STRING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING, - JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, - JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN, - JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC, - JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL, - JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT -} JS_ENUM_FOOTER(JSValueTag); - -static_assert(sizeof(JSValueTag) == sizeof(uint32_t), - "compiler typed enum support is apparently buggy"); - -JS_ENUM_HEADER(JSValueShiftedTag, uint64_t) -{ - JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF), - JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) -} JS_ENUM_FOOTER(JSValueShiftedTag); - -static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t), - "compiler typed enum support is apparently buggy"); - -#endif - -/* - * All our supported compilers implement C++11 |enum Foo : T| syntax, so don't - * expose these macros. (This macro exists *only* because gcc bug 51242 - * makes bit-fields of - * typed enums trigger a warning that can't be turned off. Don't expose it - * beyond this file!) - */ -#undef JS_ENUM_HEADER -#undef JS_ENUM_FOOTER - -#else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ - -typedef uint8_t JSValueType; -#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00) -#define JSVAL_TYPE_INT32 ((uint8_t)0x01) -#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02) -#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03) -#define JSVAL_TYPE_MAGIC ((uint8_t)0x04) -#define JSVAL_TYPE_STRING ((uint8_t)0x05) -#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06) -#define JSVAL_TYPE_NULL ((uint8_t)0x07) -#define JSVAL_TYPE_OBJECT ((uint8_t)0x08) -#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20) - -#if defined(JS_NUNBOX32) - -typedef uint32_t JSValueTag; -#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80)) -#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32)) -#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED)) -#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING)) -#define JSVAL_TAG_SYMBOL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL)) -#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN)) -#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC)) -#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL)) -#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT)) - -#elif defined(JS_PUNBOX64) - -typedef uint32_t JSValueTag; -#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0)) -#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) -#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED) -#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING) -#define JSVAL_TAG_SYMBOL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL) -#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) -#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC) -#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL) -#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT) - -typedef uint64_t JSValueShiftedTag; -#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF) -#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) - -#endif /* JS_PUNBOX64 */ -#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ - -#if defined(JS_NUNBOX32) - -#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) - -#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL -#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT -#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 -#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING - -#elif defined(JS_PUNBOX64) - -#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL -#define JSVAL_TAG_MASK 0xFFFF800000000000LL -#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type))) -#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT) - -#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL -#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT -#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 -#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING - -#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL -#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT -#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED -#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING - -#endif /* JS_PUNBOX64 */ - -typedef enum JSWhyMagic -{ - /** a hole in a native object's elements */ - JS_ELEMENTS_HOLE, - - /** there is not a pending iterator value */ - JS_NO_ITER_VALUE, - - /** exception value thrown when closing a generator */ - JS_GENERATOR_CLOSING, - - /** compiler sentinel value */ - JS_NO_CONSTANT, - - /** used in debug builds to catch tracing errors */ - JS_THIS_POISON, - - /** used in debug builds to catch tracing errors */ - JS_ARG_POISON, - - /** an empty subnode in the AST serializer */ - JS_SERIALIZE_NO_NODE, - - /** lazy arguments value on the stack */ - JS_LAZY_ARGUMENTS, - - /** optimized-away 'arguments' value */ - JS_OPTIMIZED_ARGUMENTS, - - /** magic value passed to natives to indicate construction */ - JS_IS_CONSTRUCTING, - - /** arguments.callee has been overwritten */ - JS_OVERWRITTEN_CALLEE, - - /** value of static block object slot */ - JS_BLOCK_NEEDS_CLONE, - - /** see class js::HashableValue */ - JS_HASH_KEY_EMPTY, - - /** error while running Ion code */ - JS_ION_ERROR, - - /** missing recover instruction result */ - JS_ION_BAILOUT, - - /** optimized out slot */ - JS_OPTIMIZED_OUT, - - /** uninitialized lexical bindings that produce ReferenceError on touch. */ - JS_UNINITIALIZED_LEXICAL, - - /** for local use */ - JS_GENERIC_MAGIC, - - JS_WHY_MAGIC_COUNT -} JSWhyMagic; - -#if defined(IS_LITTLE_ENDIAN) -# if defined(JS_NUNBOX32) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - union { - int32_t i32; - uint32_t u32; - uint32_t boo; // Don't use |bool| -- it must be four bytes. - JSString* str; - JS::Symbol* sym; - JSObject* obj; - js::gc::Cell* cell; - void* ptr; - JSWhyMagic why; - size_t word; - uintptr_t uintptr; - } payload; - JSValueTag tag; - } s; - double asDouble; - void* asPtr; -} JSVAL_ALIGNMENT jsval_layout; -# elif defined(JS_PUNBOX64) -typedef union jsval_layout -{ - uint64_t asBits; -#if !defined(_WIN64) - /* MSVC does not pack these correctly :-( */ - struct { - uint64_t payload47 : 47; - JSValueTag tag : 17; - } debugView; -#endif - struct { - union { - int32_t i32; - uint32_t u32; - JSWhyMagic why; - } payload; - } s; - double asDouble; - void* asPtr; - size_t asWord; - uintptr_t asUIntPtr; -} JSVAL_ALIGNMENT jsval_layout; -# endif /* JS_PUNBOX64 */ -#else /* defined(IS_LITTLE_ENDIAN) */ -# if defined(JS_NUNBOX32) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - JSValueTag tag; - union { - int32_t i32; - uint32_t u32; - uint32_t boo; // Don't use |bool| -- it must be four bytes. - JSString* str; - JS::Symbol* sym; - JSObject* obj; - js::gc::Cell* cell; - void* ptr; - JSWhyMagic why; - size_t word; - uintptr_t uintptr; - } payload; - } s; - double asDouble; - void* asPtr; -} JSVAL_ALIGNMENT jsval_layout; -# elif defined(JS_PUNBOX64) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - JSValueTag tag : 17; - uint64_t payload47 : 47; - } debugView; - struct { - uint32_t padding; - union { - int32_t i32; - uint32_t u32; - JSWhyMagic why; - } payload; - } s; - double asDouble; - void* asPtr; - size_t asWord; - uintptr_t asUIntPtr; -} JSVAL_ALIGNMENT jsval_layout; -# endif /* JS_PUNBOX64 */ -#endif /* defined(IS_LITTLE_ENDIAN) */ - -/* - * For codesize purposes on some platforms, it's important that the - * compiler know that JS::Values constructed from constant values can be - * folded to constant bit patterns at compile time, rather than - * constructed at runtime. Doing this requires a fair amount of C++11 - * features, which are not supported on all of our compilers. Set up - * some defines and helper macros in an attempt to confine the ugliness - * here, rather than scattering it all about the file. The important - * features are: - * - * - constexpr; - * - defaulted functions; - * - C99-style designated initializers. - */ -#if defined(__clang__) -# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions) -# define JS_VALUE_IS_CONSTEXPR -# endif -#elif defined(__GNUC__) -/* - * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6 - * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because - * versions prior to that have bugs in the C++ front-end that cause crashes. - */ -# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3) -# define JS_VALUE_IS_CONSTEXPR -# endif -#endif - -#if defined(JS_VALUE_IS_CONSTEXPR) -# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ - return (jsval_layout) { .asBits = (BITS) } -# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR -# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR -#else -# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ - jsval_layout l; \ - l.asBits = (BITS); \ - return l; -# define JS_VALUE_CONSTEXPR -# define JS_VALUE_CONSTEXPR_VAR const -#endif - -struct Value { - jsval_layout data; -}; diff --git a/tests/headers/layout.h b/tests/headers/layout.h deleted file mode 100644 index d1822a04de..0000000000 --- a/tests/headers/layout.h +++ /dev/null @@ -1,6 +0,0 @@ -struct header -{ - char proto; - unsigned int size __attribute__ ((packed)); - unsigned char data[] __attribute__ ((aligned(8))); -} __attribute__ ((aligned, packed)); \ No newline at end of file diff --git a/tests/headers/layout_eth_conf_1_0.h b/tests/headers/layout_eth_conf_1_0.h deleted file mode 100644 index cf6fa6ad2e..0000000000 --- a/tests/headers/layout_eth_conf_1_0.h +++ /dev/null @@ -1,429 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum .* - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -/** - * Simple flags are used for rte_eth_conf.rxmode.mq_mode. - */ -#define ETH_MQ_RX_RSS_FLAG 0x1 -#define ETH_MQ_RX_DCB_FLAG 0x2 -#define ETH_MQ_RX_VMDQ_FLAG 0x4 - -/* Definitions used for VMDQ and DCB functionality */ -#define ETH_VMDQ_MAX_VLAN_FILTERS 64 /**< Maximum nb. of VMDQ vlan filters. */ -#define ETH_DCB_NUM_USER_PRIORITIES 8 /**< Maximum nb. of DCB priorities. */ -#define ETH_VMDQ_DCB_NUM_QUEUES 128 /**< Maximum nb. of VMDQ DCB queues. */ -#define ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */ - -/** - * A set of values to identify what method is to be used to route - * packets to multiple queues. - */ -enum rte_eth_rx_mq_mode { - /** None of DCB,RSS or VMDQ mode */ - ETH_MQ_RX_NONE = 0, - - /** For RX side, only RSS is on */ - ETH_MQ_RX_RSS = ETH_MQ_RX_RSS_FLAG, - /** For RX side,only DCB is on. */ - ETH_MQ_RX_DCB = ETH_MQ_RX_DCB_FLAG, - /** Both DCB and RSS enable */ - ETH_MQ_RX_DCB_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_DCB_FLAG, - - /** Only VMDQ, no RSS nor DCB */ - ETH_MQ_RX_VMDQ_ONLY = ETH_MQ_RX_VMDQ_FLAG, - /** RSS mode with VMDQ */ - ETH_MQ_RX_VMDQ_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_VMDQ_FLAG, - /** Use VMDQ+DCB to route traffic to queues */ - ETH_MQ_RX_VMDQ_DCB = ETH_MQ_RX_VMDQ_FLAG | ETH_MQ_RX_DCB_FLAG, - /** Enable both VMDQ and DCB in VMDq */ - ETH_MQ_RX_VMDQ_DCB_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_DCB_FLAG | - ETH_MQ_RX_VMDQ_FLAG, -}; - -/** - * A structure used to configure the RX features of an Ethernet port. - */ -struct rte_eth_rxmode { - /** The multi-queue packet distribution mode to be used, e.g. RSS. */ - enum rte_eth_rx_mq_mode mq_mode; - uint32_t max_rx_pkt_len; /**< Only used if jumbo_frame enabled. */ - uint16_t split_hdr_size; /**< hdr buf size (header_split enabled).*/ - __extension__ - uint16_t header_split : 1, /**< Header Split enable. */ - hw_ip_checksum : 1, /**< IP/UDP/TCP checksum offload enable. */ - hw_vlan_filter : 1, /**< VLAN filter enable. */ - hw_vlan_strip : 1, /**< VLAN strip enable. */ - hw_vlan_extend : 1, /**< Extended VLAN enable. */ - jumbo_frame : 1, /**< Jumbo Frame Receipt enable. */ - hw_strip_crc : 1, /**< Enable CRC stripping by hardware. */ - enable_scatter : 1, /**< Enable scatter packets rx handler */ - enable_lro : 1; /**< Enable LRO */ -}; - -/** - * A set of values to identify what method is to be used to transmit - * packets using multi-TCs. - */ -enum rte_eth_tx_mq_mode { - ETH_MQ_TX_NONE = 0, /**< It is in neither DCB nor VT mode. */ - ETH_MQ_TX_DCB, /**< For TX side,only DCB is on. */ - ETH_MQ_TX_VMDQ_DCB, /**< For TX side,both DCB and VT is on. */ - ETH_MQ_TX_VMDQ_ONLY, /**< Only VT on, no DCB */ -}; - -/** - * A structure used to configure the TX features of an Ethernet port. - */ -struct rte_eth_txmode { - enum rte_eth_tx_mq_mode mq_mode; /**< TX multi-queues mode. */ - - /* For i40e specifically */ - uint16_t pvid; - __extension__ - uint8_t hw_vlan_reject_tagged : 1, - /**< If set, reject sending out tagged pkts */ - hw_vlan_reject_untagged : 1, - /**< If set, reject sending out untagged pkts */ - hw_vlan_insert_pvid : 1; - /**< If set, enable port based VLAN insertion */ -}; - -/** - * A structure used to configure the Receive Side Scaling (RSS) feature - * of an Ethernet port. - * If not NULL, the *rss_key* pointer of the *rss_conf* structure points - * to an array holding the RSS key to use for hashing specific header - * fields of received packets. The length of this array should be indicated - * by *rss_key_len* below. Otherwise, a default random hash key is used by - * the device driver. - * - * The *rss_key_len* field of the *rss_conf* structure indicates the length - * in bytes of the array pointed by *rss_key*. To be compatible, this length - * will be checked in i40e only. Others assume 40 bytes to be used as before. - * - * The *rss_hf* field of the *rss_conf* structure indicates the different - * types of IPv4/IPv6 packets to which the RSS hashing must be applied. - * Supplying an *rss_hf* equal to zero disables the RSS feature. - */ -struct rte_eth_rss_conf { - uint8_t *rss_key; /**< If not NULL, 40-byte hash key. */ - uint8_t rss_key_len; /**< hash key length in bytes. */ - uint64_t rss_hf; /**< Hash functions to apply - see below. */ -}; - -/** - * This enum indicates the possible number of traffic classes - * in DCB configratioins - */ -enum rte_eth_nb_tcs { - ETH_4_TCS = 4, /**< 4 TCs with DCB. */ - ETH_8_TCS = 8 /**< 8 TCs with DCB. */ -}; - -/** - * This enum indicates the possible number of queue pools - * in VMDQ configurations. - */ -enum rte_eth_nb_pools { - ETH_8_POOLS = 8, /**< 8 VMDq pools. */ - ETH_16_POOLS = 16, /**< 16 VMDq pools. */ - ETH_32_POOLS = 32, /**< 32 VMDq pools. */ - ETH_64_POOLS = 64 /**< 64 VMDq pools. */ -}; - -/** - * A structure used to configure the VMDQ+DCB feature - * of an Ethernet port. - * - * Using this feature, packets are routed to a pool of queues, based - * on the vlan id in the vlan tag, and then to a specific queue within - * that pool, using the user priority vlan tag field. - * - * A default pool may be used, if desired, to route all traffic which - * does not match the vlan filter rules. - */ -struct rte_eth_vmdq_dcb_conf { - enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools */ - uint8_t enable_default_pool; /**< If non-zero, use a default pool */ - uint8_t default_pool; /**< The default pool, if applicable */ - uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ - struct { - uint16_t vlan_id; /**< The vlan id of the received frame */ - uint64_t pools; /**< Bitmask of pools for packet rx */ - } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ - uint8_t dcb_tc[ETH_DCB_NUM_USER_PRIORITIES]; - /**< Selects a queue in a pool */ -}; - -/* This structure may be extended in future. */ -struct rte_eth_dcb_rx_conf { - enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */ - /** Traffic class each UP mapped to. */ - uint8_t dcb_tc[ETH_DCB_NUM_USER_PRIORITIES]; -}; - -struct rte_eth_vmdq_dcb_tx_conf { - enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools. */ - /** Traffic class each UP mapped to. */ - uint8_t dcb_tc[ETH_DCB_NUM_USER_PRIORITIES]; -}; - -struct rte_eth_dcb_tx_conf { - enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs. */ - /** Traffic class each UP mapped to. */ - uint8_t dcb_tc[ETH_DCB_NUM_USER_PRIORITIES]; -}; - -struct rte_eth_vmdq_tx_conf { - enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */ -}; - -struct rte_eth_vmdq_rx_conf { - enum rte_eth_nb_pools nb_queue_pools; /**< VMDq only mode, 8 or 64 pools */ - uint8_t enable_default_pool; /**< If non-zero, use a default pool */ - uint8_t default_pool; /**< The default pool, if applicable */ - uint8_t enable_loop_back; /**< Enable VT loop back */ - uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ - uint32_t rx_mode; /**< Flags from ETH_VMDQ_ACCEPT_* */ - struct { - uint16_t vlan_id; /**< The vlan id of the received frame */ - uint64_t pools; /**< Bitmask of pools for packet rx */ - } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ -}; - -/** - * Flow Director setting modes: none, signature or perfect. - */ -enum rte_fdir_mode { - RTE_FDIR_MODE_NONE = 0, /**< Disable FDIR support. */ - RTE_FDIR_MODE_SIGNATURE, /**< Enable FDIR signature filter mode. */ - RTE_FDIR_MODE_PERFECT, /**< Enable FDIR perfect filter mode. */ - RTE_FDIR_MODE_PERFECT_MAC_VLAN, /**< Enable FDIR filter mode - MAC VLAN. */ - RTE_FDIR_MODE_PERFECT_TUNNEL, /**< Enable FDIR filter mode - tunnel. */ -}; - -/** - * Memory space that can be configured to store Flow Director filters - * in the board memory. - */ -enum rte_fdir_pballoc_type { - RTE_FDIR_PBALLOC_64K = 0, /**< 64k. */ - RTE_FDIR_PBALLOC_128K, /**< 128k. */ - RTE_FDIR_PBALLOC_256K, /**< 256k. */ -}; - -/** - * Select report mode of FDIR hash information in RX descriptors. - */ -enum rte_fdir_status_mode { - RTE_FDIR_NO_REPORT_STATUS = 0, /**< Never report FDIR hash. */ - RTE_FDIR_REPORT_STATUS, /**< Only report FDIR hash for matching pkts. */ - RTE_FDIR_REPORT_STATUS_ALWAYS, /**< Always report FDIR hash. */ -}; - -/** - * A structure used to define the input for IPV4 flow - */ -struct rte_eth_ipv4_flow { - uint32_t src_ip; /**< IPv4 source address in big endian. */ - uint32_t dst_ip; /**< IPv4 destination address in big endian. */ - uint8_t tos; /**< Type of service to match. */ - uint8_t ttl; /**< Time to live to match. */ - uint8_t proto; /**< Protocol, next header in big endian. */ -}; - -/** - * A structure used to define the input for IPV6 flow - */ -struct rte_eth_ipv6_flow { - uint32_t src_ip[4]; /**< IPv6 source address in big endian. */ - uint32_t dst_ip[4]; /**< IPv6 destination address in big endian. */ - uint8_t tc; /**< Traffic class to match. */ - uint8_t proto; /**< Protocol, next header to match. */ - uint8_t hop_limits; /**< Hop limits to match. */ -}; - -/** - * A structure used to configure FDIR masks that are used by the device - * to match the various fields of RX packet headers. - */ -struct rte_eth_fdir_masks { - uint16_t vlan_tci_mask; /**< Bit mask for vlan_tci in big endian */ - /** Bit mask for ipv4 flow in big endian. */ - struct rte_eth_ipv4_flow ipv4_mask; - /** Bit maks for ipv6 flow in big endian. */ - struct rte_eth_ipv6_flow ipv6_mask; - /** Bit mask for L4 source port in big endian. */ - uint16_t src_port_mask; - /** Bit mask for L4 destination port in big endian. */ - uint16_t dst_port_mask; - /** 6 bit mask for proper 6 bytes of Mac address, bit 0 matches the - first byte on the wire */ - uint8_t mac_addr_byte_mask; - /** Bit mask for tunnel ID in big endian. */ - uint32_t tunnel_id_mask; - uint8_t tunnel_type_mask; /**< 1 - Match tunnel type, - 0 - Ignore tunnel type. */ -}; - -/** - * Payload type - */ -enum rte_eth_payload_type { - RTE_ETH_PAYLOAD_UNKNOWN = 0, - RTE_ETH_RAW_PAYLOAD, - RTE_ETH_L2_PAYLOAD, - RTE_ETH_L3_PAYLOAD, - RTE_ETH_L4_PAYLOAD, - RTE_ETH_PAYLOAD_MAX = 8, -}; - -#define RTE_ETH_FDIR_MAX_FLEXLEN 16 /**< Max length of flexbytes. */ -#define RTE_ETH_INSET_SIZE_MAX 128 /**< Max length of input set. */ - -/** - * A structure used to select bytes extracted from the protocol layers to - * flexible payload for filter - */ -struct rte_eth_flex_payload_cfg { - enum rte_eth_payload_type type; /**< Payload type */ - uint16_t src_offset[RTE_ETH_FDIR_MAX_FLEXLEN]; - /**< Offset in bytes from the beginning of packet's payload - src_offset[i] indicates the flexbyte i's offset in original - packet payload. This value should be less than - flex_payload_limit in struct rte_eth_fdir_info.*/ -}; - -/** - * A structure used to define FDIR masks for flexible payload - * for each flow type - */ -struct rte_eth_fdir_flex_mask { - uint16_t flow_type; - uint8_t mask[RTE_ETH_FDIR_MAX_FLEXLEN]; - /**< Mask for the whole flexible payload */ -}; - - -/* - * A packet can be identified by hardware as different flow types. Different - * NIC hardwares may support different flow types. - * Basically, the NIC hardware identifies the flow type as deep protocol as - * possible, and exclusively. For example, if a packet is identified as - * 'RTE_ETH_FLOW_NONFRAG_IPV4_TCP', it will not be any of other flow types, - * though it is an actual IPV4 packet. - * Note that the flow types are used to define RSS offload types in - * rte_ethdev.h. - */ -#define RTE_ETH_FLOW_UNKNOWN 0 -#define RTE_ETH_FLOW_RAW 1 -#define RTE_ETH_FLOW_IPV4 2 -#define RTE_ETH_FLOW_FRAG_IPV4 3 -#define RTE_ETH_FLOW_NONFRAG_IPV4_TCP 4 -#define RTE_ETH_FLOW_NONFRAG_IPV4_UDP 5 -#define RTE_ETH_FLOW_NONFRAG_IPV4_SCTP 6 -#define RTE_ETH_FLOW_NONFRAG_IPV4_OTHER 7 -#define RTE_ETH_FLOW_IPV6 8 -#define RTE_ETH_FLOW_FRAG_IPV6 9 -#define RTE_ETH_FLOW_NONFRAG_IPV6_TCP 10 -#define RTE_ETH_FLOW_NONFRAG_IPV6_UDP 11 -#define RTE_ETH_FLOW_NONFRAG_IPV6_SCTP 12 -#define RTE_ETH_FLOW_NONFRAG_IPV6_OTHER 13 -#define RTE_ETH_FLOW_L2_PAYLOAD 14 -#define RTE_ETH_FLOW_IPV6_EX 15 -#define RTE_ETH_FLOW_IPV6_TCP_EX 16 -#define RTE_ETH_FLOW_IPV6_UDP_EX 17 -#define RTE_ETH_FLOW_PORT 18 - /**< Consider device port number as a flow differentiator */ -#define RTE_ETH_FLOW_VXLAN 19 /**< VXLAN protocol based flow */ -#define RTE_ETH_FLOW_GENEVE 20 /**< GENEVE protocol based flow */ -#define RTE_ETH_FLOW_NVGRE 21 /**< NVGRE protocol based flow */ -#define RTE_ETH_FLOW_MAX 22 - -/** - * A structure used to define all flexible payload related setting - * include flex payload and flex mask - */ -struct rte_eth_fdir_flex_conf { - uint16_t nb_payloads; /**< The number of following payload cfg */ - uint16_t nb_flexmasks; /**< The number of following mask */ - struct rte_eth_flex_payload_cfg flex_set[RTE_ETH_PAYLOAD_MAX]; - /**< Flex payload configuration for each payload type */ - struct rte_eth_fdir_flex_mask flex_mask[RTE_ETH_FLOW_MAX]; - /**< Flex mask configuration for each flow type */ -}; - -/** - * A structure used to configure the Flow Director (FDIR) feature - * of an Ethernet port. - * - * If mode is RTE_FDIR_DISABLE, the pballoc value is ignored. - */ -struct rte_fdir_conf { - enum rte_fdir_mode mode; /**< Flow Director mode. */ - enum rte_fdir_pballoc_type pballoc; /**< Space for FDIR filters. */ - enum rte_fdir_status_mode status; /**< How to report FDIR hash. */ - /** RX queue of packets matching a "drop" filter in perfect mode. */ - uint8_t drop_queue; - struct rte_eth_fdir_masks mask; - struct rte_eth_fdir_flex_conf flex_conf; - /**< Flex payload configuration. */ -}; - -/** - * A structure used to enable/disable specific device interrupts. - */ -struct rte_intr_conf { - /** enable/disable lsc interrupt. 0 (default) - disable, 1 enable */ - uint16_t lsc; - /** enable/disable rxq interrupt. 0 (default) - disable, 1 enable */ - uint16_t rxq; -}; - -/** - * A structure used to configure an Ethernet port. - * Depending upon the RX multi-queue mode, extra advanced - * configuration settings may be needed. - */ -struct rte_eth_conf { - uint32_t link_speeds; /**< bitmap of ETH_LINK_SPEED_XXX of speeds to be - used. ETH_LINK_SPEED_FIXED disables link - autonegotiation, and a unique speed shall be - set. Otherwise, the bitmap defines the set of - speeds to be advertised. If the special value - ETH_LINK_SPEED_AUTONEG (0) is used, all speeds - supported are advertised. */ - struct rte_eth_rxmode rxmode; /**< Port RX configuration. */ - struct rte_eth_txmode txmode; /**< Port TX configuration. */ - uint32_t lpbk_mode; /**< Loopback operation mode. By default the value - is 0, meaning the loopback mode is disabled. - Read the datasheet of given ethernet controller - for details. The possible values of this field - are defined in implementation of each driver. */ - struct { - struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */ - struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf; - /**< Port vmdq+dcb configuration. */ - struct rte_eth_dcb_rx_conf dcb_rx_conf; - /**< Port dcb RX configuration. */ - struct rte_eth_vmdq_rx_conf vmdq_rx_conf; - /**< Port vmdq RX configuration. */ - } rx_adv_conf; /**< Port RX filtering configuration (union). */ - union { - struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf; - /**< Port vmdq+dcb TX configuration. */ - struct rte_eth_dcb_tx_conf dcb_tx_conf; - /**< Port dcb TX configuration. */ - struct rte_eth_vmdq_tx_conf vmdq_tx_conf; - /**< Port vmdq TX configuration. */ - } tx_adv_conf; /**< Port TX DCB configuration (union). */ - /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC - is needed,and the variable must be set ETH_DCB_PFC_SUPPORT. */ - uint32_t dcb_capability_en; - struct rte_fdir_conf fdir_conf; /**< FDIR configuration. */ - struct rte_intr_conf intr_conf; /**< Interrupt mode configuration. */ -}; diff --git a/tests/headers/layout_mbuf_1_0.h b/tests/headers/layout_mbuf_1_0.h deleted file mode 100644 index 2854de5038..0000000000 --- a/tests/headers/layout_mbuf_1_0.h +++ /dev/null @@ -1,189 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - - -#define RTE_CACHE_LINE_MIN_SIZE 64 /**< Minimum Cache line size. */ - -#define RTE_CACHE_LINE_SIZE 64 - -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -typedef uint64_t phys_addr_t; - -/** - * Force alignment - */ -#define __rte_aligned(a) __attribute__((__aligned__(a))) - -/** - * Force alignment to cache line. - */ -#define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) - -/** - * Force minimum cache line alignment. - */ -#define __rte_cache_min_aligned __rte_aligned(RTE_CACHE_LINE_MIN_SIZE) - -/* define a set of marker types that can be used to refer to set points in the - * mbuf */ -__extension__ -typedef void *MARKER[0]; /**< generic marker for a point in a structure */ -__extension__ -typedef uint8_t MARKER8[0]; /**< generic marker with 1B alignment */ -__extension__ -typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes - * with a single assignment */ - -/** C extension macro for environments lacking C11 features. */ -#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L -#define RTE_STD_C11 __extension__ -#else -#define RTE_STD_C11 -#endif - -/** - * The atomic counter structure. - */ -typedef struct { - volatile int16_t cnt; /**< An internal counter value. */ -} rte_atomic16_t; - -/** - * The generic rte_mbuf, containing a packet mbuf. - */ -struct rte_mbuf { - MARKER cacheline0; - - void *buf_addr; /**< Virtual address of segment buffer. */ - phys_addr_t buf_physaddr; /**< Physical address of segment buffer. */ - - uint16_t buf_len; /**< Length of segment buffer. */ - - /* next 6 bytes are initialised on RX descriptor rearm */ - MARKER8 rearm_data; - uint16_t data_off; - - /** - * 16-bit Reference counter. - * It should only be accessed using the following functions: - * rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and - * rte_mbuf_refcnt_set(). The functionality of these functions (atomic, - * or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC - * config option. - */ - RTE_STD_C11 - union { - rte_atomic16_t refcnt_atomic; /**< Atomically accessed refcnt */ - uint16_t refcnt; /**< Non-atomically accessed refcnt */ - }; - uint8_t nb_segs; /**< Number of segments. */ - uint8_t port; /**< Input port. */ - - uint64_t ol_flags; /**< Offload features. */ - - /* remaining bytes are set on RX when pulling packet from descriptor */ - MARKER rx_descriptor_fields1; - - /* - * The packet type, which is the combination of outer/inner L2, L3, L4 - * and tunnel types. The packet_type is about data really present in the - * mbuf. Example: if vlan stripping is enabled, a received vlan packet - * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the - * vlan is stripped from the data. - */ - RTE_STD_C11 - union { - uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */ - struct { - uint32_t l2_type:4; /**< (Outer) L2 type. */ - uint32_t l3_type:4; /**< (Outer) L3 type. */ - uint32_t l4_type:4; /**< (Outer) L4 type. */ - uint32_t tun_type:4; /**< Tunnel type. */ - uint32_t inner_l2_type:4; /**< Inner L2 type. */ - uint32_t inner_l3_type:4; /**< Inner L3 type. */ - uint32_t inner_l4_type:4; /**< Inner L4 type. */ - }; - }; - - uint32_t pkt_len; /**< Total pkt len: sum of all segments. */ - uint16_t data_len; /**< Amount of data in segment buffer. */ - /** VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. */ - uint16_t vlan_tci; - - union { - uint32_t rss; /**< RSS hash result if RSS enabled */ - struct { - RTE_STD_C11 - union { - struct { - uint16_t hash; - uint16_t id; - }; - uint32_t lo; - /**< Second 4 flexible bytes */ - }; - uint32_t hi; - /**< First 4 flexible bytes or FD ID, dependent on - PKT_RX_FDIR_* flag in ol_flags. */ - } fdir; /**< Filter identifier if FDIR enabled */ - struct { - uint32_t lo; - uint32_t hi; - } sched; /**< Hierarchical scheduler */ - uint32_t usr; /**< User defined tags. See rte_distributor_process() */ - } hash; /**< hash information */ - - uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */ - - /** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. */ - uint16_t vlan_tci_outer; - - /* second cache line - fields only used in slow path or on TX */ - MARKER cacheline1 __rte_cache_min_aligned; - - RTE_STD_C11 - union { - void *userdata; /**< Can be used for external metadata */ - uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */ - }; - - struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */ - struct rte_mbuf *next; /**< Next segment of scattered packet. */ - - /* fields to support TX offloads */ - RTE_STD_C11 - union { - uint64_t tx_offload; /**< combined for easy fetch */ - __extension__ - struct { - uint64_t l2_len:7; - /**< L2 (MAC) Header Length for non-tunneling pkt. - * Outer_L4_len + ... + Inner_L2_len for tunneling pkt. - */ - uint64_t l3_len:9; /**< L3 (IP) Header Length. */ - uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */ - uint64_t tso_segsz:16; /**< TCP TSO segment size */ - - /* fields for TX offloading of tunnels */ - uint64_t outer_l3_len:9; /**< Outer L3 (IP) Hdr Length. */ - uint64_t outer_l2_len:7; /**< Outer L2 (MAC) Hdr Length. */ - - /* uint64_t unused:8; */ - }; - }; - - /** Size of the application private data. In case of an indirect - * mbuf, it stores the direct mbuf private data size. */ - uint16_t priv_size; - - /** Timesync flags for use with IEEE1588. */ - uint16_t timesync; -} __rte_cache_aligned; diff --git a/tests/headers/maddness-is-avoidable.hpp b/tests/headers/maddness-is-avoidable.hpp deleted file mode 100644 index 46d7495ead..0000000000 --- a/tests/headers/maddness-is-avoidable.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --blacklist-type RefPtr_Proxy_member_function - -template -class RefPtr { - template - class Proxy { - typedef R (T::*member_function)(Args...); - }; -}; diff --git a/tests/headers/mangling-win32.hpp b/tests/headers/mangling-win32.hpp deleted file mode 100644 index 50beea5aec..0000000000 --- a/tests/headers/mangling-win32.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: -- --target=i686-pc-win32 - -extern "C" void foo(); - -struct Foo { - static bool sBar; -}; diff --git a/tests/headers/namespace.hpp b/tests/headers/namespace.hpp deleted file mode 100644 index 408207f2c3..0000000000 --- a/tests/headers/namespace.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces - -void top_level(); - -namespace whatever { - typedef int whatever_int_t; - - void in_whatever(); -} - -namespace { - namespace empty {} - - struct A { - whatever::whatever_int_t b; - }; -} - -template -class C: public A { - T m_c; - T* m_c_ptr; - T m_c_arr[10]; -}; - -template<> -class C; - -namespace w { - typedef unsigned int whatever_int_t; - - template - class D { - C m_c; - }; - - whatever_int_t heh(); // this should return w::whatever_int_t, and not whatever::whatever_int_t - - C foo(); - - C barr(); // <- This is the problematic one -} diff --git a/tests/headers/no-hash-whitelisted.hpp b/tests/headers/no-hash-whitelisted.hpp deleted file mode 100644 index 77c9086438..0000000000 --- a/tests/headers/no-hash-whitelisted.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --with-derive-hash --whitelist-type "NoHash" --no-hash "NoHash" - -class NoHash { - int i; -}; diff --git a/tests/headers/no-partialeq-whitelisted.hpp b/tests/headers/no-partialeq-whitelisted.hpp deleted file mode 100644 index dba4e91f76..0000000000 --- a/tests/headers/no-partialeq-whitelisted.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --with-derive-partialeq --whitelist-type "NoPartialEq" --no-partialeq "NoPartialEq" - -class NoPartialEq { - int i; -}; diff --git a/tests/headers/no-recursive-whitelisting.h b/tests/headers/no-recursive-whitelisting.h deleted file mode 100644 index 8eb8afea14..0000000000 --- a/tests/headers/no-recursive-whitelisting.h +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --no-recursive-whitelist --whitelist-type "Foo" --raw-line "pub enum Bar {}" --rustified-enum .* - -struct Bar; - -struct Foo { - struct Bar* baz; -}; diff --git a/tests/headers/no_copy_whitelisted.hpp b/tests/headers/no_copy_whitelisted.hpp deleted file mode 100644 index db44a8a7eb..0000000000 --- a/tests/headers/no_copy_whitelisted.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --whitelist-type "NoCopy" --no-copy "NoCopy" - -class NoCopy { - int i; -}; diff --git a/tests/headers/objc_category.h b/tests/headers/objc_category.h deleted file mode 100644 index c464b72eb2..0000000000 --- a/tests/headers/objc_category.h +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo --(void)method; -@end - -@interface Foo (BarCategory) --(void)categoryMethod; -@end diff --git a/tests/headers/objc_class.h b/tests/headers/objc_class.h deleted file mode 100644 index cea72e78aa..0000000000 --- a/tests/headers/objc_class.h +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@class Foo; - -Foo* fooVar; - -@interface Foo --(void)method; -@end diff --git a/tests/headers/objc_interface.h b/tests/headers/objc_interface.h deleted file mode 100644 index af84bf925a..0000000000 --- a/tests/headers/objc_interface.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo -@end - -@protocol bar -@end diff --git a/tests/headers/objc_interface_type.h b/tests/headers/objc_interface_type.h deleted file mode 100644 index 31d33664c1..0000000000 --- a/tests/headers/objc_interface_type.h +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo -@end - -struct FooStruct { - Foo *foo; -}; - -void fooFunc(Foo *foo); - -static const Foo *kFoo; diff --git a/tests/headers/objc_method.h b/tests/headers/objc_method.h deleted file mode 100644 index 7a22e8e44e..0000000000 --- a/tests/headers/objc_method.h +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo -- (void)method; -- (void)methodWithInt:(int)foo; -- (void)methodWithFoo:(Foo*)foo; -- (int)methodReturningInt; -- (Foo*)methodReturningFoo; -- (void)methodWithArg1:(int)intvalue andArg2:(char*)ptr andArg3:(float)floatvalue; -@end diff --git a/tests/headers/objc_method_clash.h b/tests/headers/objc_method_clash.h deleted file mode 100644 index a56e39dba8..0000000000 --- a/tests/headers/objc_method_clash.h +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo -+ (void)foo; -- (void)foo; -@end diff --git a/tests/headers/objc_property_fnptr.h b/tests/headers/objc_property_fnptr.h deleted file mode 100644 index 8312ba4ae7..0000000000 --- a/tests/headers/objc_property_fnptr.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo -// FIXME: We are not generating valid code for this -// but at least we should not die -@property int (*func)(char, short, float); -@end diff --git a/tests/headers/objc_protocol.h b/tests/headers/objc_protocol.h deleted file mode 100644 index 0c760fa51f..0000000000 --- a/tests/headers/objc_protocol.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@protocol Foo -@end - -@interface Foo -@end diff --git a/tests/headers/objc_sel_and_id.h b/tests/headers/objc_sel_and_id.h deleted file mode 100644 index 3c8c656166..0000000000 --- a/tests/headers/objc_sel_and_id.h +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -id object; -SEL selector; - -void f(id object, SEL selector); diff --git a/tests/headers/objc_template.h b/tests/headers/objc_template.h deleted file mode 100644 index 62398eb757..0000000000 --- a/tests/headers/objc_template.h +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --objc-extern-crate -- -x objective-c -// bindgen-osx-only - -@interface Foo<__covariant ObjectType> -- (ObjectType)get; -@end diff --git a/tests/headers/objc_whitelist.h b/tests/headers/objc_whitelist.h deleted file mode 100644 index 8a3bb86917..0000000000 --- a/tests/headers/objc_whitelist.h +++ /dev/null @@ -1,24 +0,0 @@ -// bindgen-flags: --objc-extern-crate --whitelist-type WhitelistMe --whitelist-type WhitelistMe_InterestingCategory -- -x objective-c -// bindgen-osx-only - - -// Protocol should be included, since it is used by the WhitelistMe -@protocol SomeProtocol --(void)protocolMethod; -+(void)protocolClassMethod; -@end - -// The whitelisted item -@interface WhitelistMe --(void)method; -+(void)classMethod; -@end - -// This was also explicitly whitelisted -@interface WhitelistMe (InterestingCategory) -@end - -// This was not automatically whitelisted -@interface WhitelistMe (IgnoredCategory) -@end - diff --git a/tests/headers/opaque-tracing.hpp b/tests/headers/opaque-tracing.hpp deleted file mode 100644 index 326ebbe770..0000000000 --- a/tests/headers/opaque-tracing.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// bindgen-flags: --opaque-type=.* --whitelist-function=foo --with-derive-hash --with-derive-partialeq --with-derive-eq - -class Container; - -// The whitelist tracing should reach the Container type, even though it's -// marked as opaque. -void foo(Container* c); - -template -class Wat { - T foo; -}; - -class OtherOpaque { - int bar; -}; - -class Container { - Wat bar; - OtherOpaque baz; -}; diff --git a/tests/headers/overflowed_enum.hpp b/tests/headers/overflowed_enum.hpp deleted file mode 100644 index 53a05ddf82..0000000000 --- a/tests/headers/overflowed_enum.hpp +++ /dev/null @@ -1,12 +0,0 @@ -// bindgen-flags: --rustified-enum .* -- -std=c++11 -Wno-narrowing - -enum Foo { - BAP_ARM = 0x93fcb9, - BAP_X86 = 0xb67eed, - BAP_X86_64 = 0xba7b274f, -}; - -enum Bar: unsigned short { - One = 1, - Big = 65538, -}; diff --git a/tests/headers/prepend-enum-constified-variant.h b/tests/headers/prepend-enum-constified-variant.h deleted file mode 100644 index 06ae264f07..0000000000 --- a/tests/headers/prepend-enum-constified-variant.h +++ /dev/null @@ -1,6 +0,0 @@ -// bindgen-flags: --no-prepend-enum-name --rustified-enum .* - -enum AVCodecID { - AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, - AV_CODEC_ID_TTF = 0x18000, -}; diff --git a/tests/headers/public-dtor.hpp b/tests/headers/public-dtor.hpp deleted file mode 100644 index 5d4fb592a1..0000000000 --- a/tests/headers/public-dtor.hpp +++ /dev/null @@ -1,15 +0,0 @@ - - -namespace cv { -class String { -public: - ~String(); -}; - - -inline -String::~String() -{ -} - -} diff --git a/tests/headers/repr-align.hpp b/tests/headers/repr-align.hpp deleted file mode 100644 index 3347594b5c..0000000000 --- a/tests/headers/repr-align.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --raw-line '#![cfg(feature = "nightly")]' --rust-target 1.25 -- -std=c++11 - -struct alignas(8) a { - int b; - int c; -}; - -struct alignas(double) b { - int b; - int c; -}; diff --git a/tests/headers/struct_with_anon_union_1_0.h b/tests/headers/struct_with_anon_union_1_0.h deleted file mode 100644 index 847c354b59..0000000000 --- a/tests/headers/struct_with_anon_union_1_0.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct foo { - union { - unsigned int a; - unsigned short b; - } bar; -}; diff --git a/tests/headers/struct_with_anon_unnamed_union_1_0.h b/tests/headers/struct_with_anon_unnamed_union_1_0.h deleted file mode 100644 index 791a1593af..0000000000 --- a/tests/headers/struct_with_anon_unnamed_union_1_0.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct foo { - union { - unsigned int a; - unsigned short b; - }; -}; diff --git a/tests/headers/struct_with_nesting_1_0.h b/tests/headers/struct_with_nesting_1_0.h deleted file mode 100644 index a24ae1db58..0000000000 --- a/tests/headers/struct_with_nesting_1_0.h +++ /dev/null @@ -1,19 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct foo { - unsigned int a; - union { - unsigned int b; - struct { - unsigned short c1; - unsigned short c2; - }; - - struct { - unsigned char d1; - unsigned char d2; - unsigned char d3; - unsigned char d4; - }; - }; -}; diff --git a/tests/headers/type-referenced-by-whitelisted-function.h b/tests/headers/type-referenced-by-whitelisted-function.h deleted file mode 100644 index 86b0030300..0000000000 --- a/tests/headers/type-referenced-by-whitelisted-function.h +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --whitelist-function dl_iterate_phdr - -struct dl_phdr_info { - int x; -}; - -int dl_iterate_phdr(struct dl_phdr_info *); diff --git a/tests/headers/type_alias_empty.hpp b/tests/headers/type_alias_empty.hpp deleted file mode 100644 index f0760c8ffd..0000000000 --- a/tests/headers/type_alias_empty.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --whitelist-type bool_constant -- -std=c++11 - -// NB: The --whitelist-type is done to trigger the traversal of the types on -// codegen in order to trigger #67. - -template -struct integral_constant {}; - -template -using bool_constant = integral_constant; diff --git a/tests/headers/typeref_1_0.hpp b/tests/headers/typeref_1_0.hpp deleted file mode 100644 index 70dfc11fb1..0000000000 --- a/tests/headers/typeref_1_0.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct nsFoo; - -namespace mozilla { - -struct FragmentOrURL { bool mIsLocalRef; }; -struct Position { }; - -} // namespace mozilla - -class Bar { - nsFoo* mFoo; -}; - -namespace mozilla { - -template -struct StyleShapeSource { - union { - Position* mPosition; - FragmentOrURL* mFragmentOrURL; - }; -}; - -} // namespace mozilla - -struct nsFoo { - mozilla::StyleShapeSource mBar; -}; diff --git a/tests/headers/union-in-ns_1_0.hpp b/tests/headers/union-in-ns_1_0.hpp deleted file mode 100644 index f3ae221057..0000000000 --- a/tests/headers/union-in-ns_1_0.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --enable-cxx-namespaces - -union bar { - int baz; -}; diff --git a/tests/headers/union_bitfield.h b/tests/headers/union_bitfield.h deleted file mode 100644 index 990729574a..0000000000 --- a/tests/headers/union_bitfield.h +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq - -union U4 { - unsigned derp : 1; -}; - -union B { - unsigned foo : 31; - unsigned char bar : 1; -}; diff --git a/tests/headers/union_bitfield_1_0.h b/tests/headers/union_bitfield_1_0.h deleted file mode 100644 index 06b61ad771..0000000000 --- a/tests/headers/union_bitfield_1_0.h +++ /dev/null @@ -1,14 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq - -union U4 { - unsigned derp : 1; -}; - -union B { - unsigned foo : 31; - unsigned char bar : 1; -}; - -union HasBigBitfield { - __int128 x : 128; -}; diff --git a/tests/headers/union_dtor_1_0.hpp b/tests/headers/union_dtor_1_0.hpp deleted file mode 100644 index 01f7636671..0000000000 --- a/tests/headers/union_dtor_1_0.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rust-target 1.0 - -union UnionWithDtor { - ~UnionWithDtor(); - int mFoo; - void* mBar; -}; diff --git a/tests/headers/union_fields_1_0.hpp b/tests/headers/union_fields_1_0.hpp deleted file mode 100644 index bbb67fbc6e..0000000000 --- a/tests/headers/union_fields_1_0.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -typedef union { - int mInt; - float mFloat; - void* mPointer; -} nsStyleUnion; diff --git a/tests/headers/union_template_1_0.hpp b/tests/headers/union_template_1_0.hpp deleted file mode 100644 index 18e3d74a37..0000000000 --- a/tests/headers/union_template_1_0.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -template -struct NastyStruct { - bool mIsSome; - union { - void* mFoo; - unsigned long mDummy; - } mStorage; - - union { - short wat; - int* wut; - }; -}; - -template -union Whatever { - void* mTPtr; - int mInt; -}; diff --git a/tests/headers/union_with_anon_struct_1_0.h b/tests/headers/union_with_anon_struct_1_0.h deleted file mode 100644 index 9313299eb0..0000000000 --- a/tests/headers/union_with_anon_struct_1_0.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union foo { - struct { - unsigned int a; - unsigned int b; - } bar; -}; diff --git a/tests/headers/union_with_anon_struct_bitfield_1_0.h b/tests/headers/union_with_anon_struct_bitfield_1_0.h deleted file mode 100644 index 0b0e3d7371..0000000000 --- a/tests/headers/union_with_anon_struct_bitfield_1_0.h +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union foo { - int a; - struct { - int b : 7; - int c : 25; - }; -}; diff --git a/tests/headers/union_with_anon_union_1_0.h b/tests/headers/union_with_anon_union_1_0.h deleted file mode 100644 index 28a7231dbf..0000000000 --- a/tests/headers/union_with_anon_union_1_0.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union foo { - union { - unsigned int a; - unsigned short b; - } bar; -}; diff --git a/tests/headers/union_with_anon_unnamed_struct_1_0.h b/tests/headers/union_with_anon_unnamed_struct_1_0.h deleted file mode 100644 index 506a41f661..0000000000 --- a/tests/headers/union_with_anon_unnamed_struct_1_0.h +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union pixel { - unsigned int rgba; - struct { - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; - }; -}; diff --git a/tests/headers/union_with_anon_unnamed_union_1_0.h b/tests/headers/union_with_anon_unnamed_union_1_0.h deleted file mode 100644 index c556a61311..0000000000 --- a/tests/headers/union_with_anon_unnamed_union_1_0.h +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union foo { - unsigned int a; - union { - unsigned short b; - unsigned char c; - }; -}; diff --git a/tests/headers/union_with_big_member_1_0.h b/tests/headers/union_with_big_member_1_0.h deleted file mode 100644 index 0429435478..0000000000 --- a/tests/headers/union_with_big_member_1_0.h +++ /dev/null @@ -1,16 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union WithBigArray { - int a; - int b[33]; -}; - -union WithBigArray2 { - int a; - char b[33]; -}; - -union WithBigMember { - int a; - union WithBigArray b; -}; diff --git a/tests/headers/union_with_nesting_1_0.h b/tests/headers/union_with_nesting_1_0.h deleted file mode 100644 index 3cdb7238bc..0000000000 --- a/tests/headers/union_with_nesting_1_0.h +++ /dev/null @@ -1,16 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq - -union foo { - unsigned int a; - struct { - union { - unsigned short b1; - unsigned short b2; - }; - - union { - unsigned short c1; - unsigned short c2; - }; - }; -}; diff --git a/tests/headers/use-core.h b/tests/headers/use-core.h deleted file mode 100644 index b4135b44a7..0000000000 --- a/tests/headers/use-core.h +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: --use-core --raw-line "extern crate core;" --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct foo { - int a, b; - void* bar; -}; - -union { - int bar; - long baz; -} bazz; - -typedef void (*fooFunction)(int bar); diff --git a/tests/headers/use-core_1_0.h b/tests/headers/use-core_1_0.h deleted file mode 100644 index 40de9d158d..0000000000 --- a/tests/headers/use-core_1_0.h +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: --rust-target 1.0 --use-core --raw-line "extern crate core;" --with-derive-hash --with-derive-partialeq --with-derive-eq - -struct foo { - int a, b; - void* bar; -}; - -union { - int bar; - long baz; -} bazz; - -typedef void (*fooFunction)(int bar); diff --git a/tests/headers/var-tracing.hpp b/tests/headers/var-tracing.hpp deleted file mode 100644 index 0d0b0ccac2..0000000000 --- a/tests/headers/var-tracing.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --whitelist-type Baz - -struct Bar { - const int m_baz; - Bar(int baz); -}; - -class Baz { - static const Bar FOO[]; -}; diff --git a/tests/headers/vector.hpp b/tests/headers/vector.hpp deleted file mode 100644 index 4707f77f46..0000000000 --- a/tests/headers/vector.hpp +++ /dev/null @@ -1,3 +0,0 @@ -struct foo { - __attribute__((__vector_size__(1 * sizeof(long long)))) long long mMember; -}; diff --git a/tests/headers/virtual_inheritance.hpp b/tests/headers/virtual_inheritance.hpp deleted file mode 100644 index 5198c51e27..0000000000 --- a/tests/headers/virtual_inheritance.hpp +++ /dev/null @@ -1,16 +0,0 @@ - -class A { - int foo; -}; - -class B: public virtual A { - int bar; -}; - -class C: public virtual A { - int baz; -}; - -class D: public C, public B { - int bazz; -}; diff --git a/tests/headers/whitelist-namespaces-basic.hpp b/tests/headers/whitelist-namespaces-basic.hpp deleted file mode 100644 index 2eaa87403e..0000000000 --- a/tests/headers/whitelist-namespaces-basic.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type outer::inner::Helper - -namespace outer { - namespace inner { - struct Helper {}; - } - struct Test { - inner::Helper helper; - }; -} diff --git a/tests/headers/whitelist-namespaces.hpp b/tests/headers/whitelist-namespaces.hpp deleted file mode 100644 index d34cbe9430..0000000000 --- a/tests/headers/whitelist-namespaces.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces --whitelist-type '.*' - -namespace outer { - namespace inner { - struct Helper {}; - } - struct Test { - inner::Helper helper; - }; -} diff --git a/tests/headers/whitelist_basic.hpp b/tests/headers/whitelist_basic.hpp deleted file mode 100644 index 8424f75a8e..0000000000 --- a/tests/headers/whitelist_basic.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// bindgen-flags: --whitelist-type WhitelistMe - -template -class WhitelistMe { - class Inner { - T bar; - }; - - int foo; - Inner bar; -}; - -struct DontWhitelistMe { - void* foo; - double _Complex noComplexGenerated; -}; diff --git a/tests/headers/whitelist_fix.hpp b/tests/headers/whitelist_fix.hpp deleted file mode 100644 index d0abda540d..0000000000 --- a/tests/headers/whitelist_fix.hpp +++ /dev/null @@ -1,4 +0,0 @@ -// bindgen-flags: --whitelist-function 'Servo_.*' --blacklist-type Test --raw-line "pub enum Test {}" - -struct Test {}; -extern "C" void Servo_Test(Test* a); diff --git a/tests/headers/whitelisted-item-references-no-hash.hpp b/tests/headers/whitelisted-item-references-no-hash.hpp deleted file mode 100644 index e656d32d0e..0000000000 --- a/tests/headers/whitelisted-item-references-no-hash.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --with-derive-hash --whitelist-type "WhitelistMe" --no-hash "NoHash" - -struct NoHash {}; - -class WhitelistMe { - NoHash a; -}; diff --git a/tests/headers/whitelisted-item-references-no-partialeq.hpp b/tests/headers/whitelisted-item-references-no-partialeq.hpp deleted file mode 100644 index d9d3d4311f..0000000000 --- a/tests/headers/whitelisted-item-references-no-partialeq.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --with-derive-partialeq --whitelist-type "WhitelistMe" --no-partialeq "NoPartialEq" - -struct NoPartialEq {}; - -class WhitelistMe { - NoPartialEq a; -}; diff --git a/tests/headers/whitelisted_item_references_no_copy.hpp b/tests/headers/whitelisted_item_references_no_copy.hpp deleted file mode 100644 index 755bbbdd49..0000000000 --- a/tests/headers/whitelisted_item_references_no_copy.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --whitelist-type "WhitelistMe" --no-copy "NoCopy" - -struct NoCopy {}; - -class WhitelistMe { - NoCopy a; -}; diff --git a/tests/headers/win32-thiscall_1_0.hpp b/tests/headers/win32-thiscall_1_0.hpp deleted file mode 100644 index 5907c76eaf..0000000000 --- a/tests/headers/win32-thiscall_1_0.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --rust-target 1.0 -- --target=i686-pc-windows-msvc - -class Foo { - public: - void test(); - int test2(int var); -}; diff --git a/tests/quickchecking/Cargo.toml b/tests/quickchecking/Cargo.toml deleted file mode 100644 index ddefb33d69..0000000000 --- a/tests/quickchecking/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "quickchecking" -description = "Bindgen property tests with quickcheck. Generate random valid C code and pass it to the csmith/predicate.py script" -version = "0.1.0" -authors = ["Shea Newton "] - -[lib] -name = "quickchecking" -path = "src/lib.rs" - -[[bin]] -name = "quickchecking" -path = "src/bin.rs" - -[dependencies] -clap = "2.28" -lazy_static = "1.0" -quickcheck = "0.4" -rand = "0.3" -tempdir = "0.3" - -[features] -# No features by default. -default = [] - -# Enable the generation of code that allows for zero sized arrays as struct -# fields. Until issues #684 and #1153 are resolved this can result in failing tests. -zero-sized-arrays = [] - -# Enable the generation of code that allows for long double types as struct -# fields. Until issue #550 is resolved this can result in failing tests. -long-doubles = [] diff --git a/tests/quickchecking/README.md b/tests/quickchecking/README.md deleted file mode 100644 index d3cfe17071..0000000000 --- a/tests/quickchecking/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Property tests for `bindgen` with `quickchecking` - -`quickchecking` generates random C headers to test `bindgen` -using the [`quickcheck`][quickcheck] property testing crate. When testing -`bindgen` with `quickchecking`, the generated header files are passed to -`bindgen`'s `csmith-fuzzing/predicate.py` script. If that script fails, -`quickchecking` panics, and you can report an issue containing the test case! - - - - - -- [Prerequisites](#prerequisites) -- [Running](#running) - - - -## Prerequisites - -Requires `python3` to be in `$PATH`. - -Many systems have `python3` by default but if your OS doesn't, its package -manager may make it available: - -``` -$ sudo apt install python3 -$ brew install python3 -$ # Etc... -``` - -## Running - -Run `quickchecking` binary to generate and test fuzzed C headers with -`cargo run`. Additional configuration is exposed through the binary's CLI. - -``` -$ cargo run --bin=quickchecking -- -h -``` -[quickcheck]: https://github.com/BurntSushi/quickcheck diff --git a/tests/quickchecking/src/bin.rs b/tests/quickchecking/src/bin.rs deleted file mode 100644 index d2774eb0d9..0000000000 --- a/tests/quickchecking/src/bin.rs +++ /dev/null @@ -1,110 +0,0 @@ -//! An application to run property tests for `bindgen` with _fuzzed_ C headers -//! using `quickcheck` -//! -//! ## Usage -//! -//! Print help -//! ```bash -//! $ cargo run --bin=quickchecking -- -h -//! ``` -//! -//! Run with default values -//! ```bash -//! $ cargo run --bin=quickchecking -//! ``` -//! -#![deny(missing_docs)] -extern crate clap; -extern crate quickchecking; - -use clap::{App, Arg}; -use std::path::Path; - -// Validate CLI argument input for generation range. -fn validate_generate_range(v: String) -> Result<(), String> { - match v.parse::() { - Ok(_) => Ok(()), - Err(_) => Err(String::from( - "Generate range could not be converted to a usize.", - )), - } -} - -// Validate CLI argument input for tests count. -fn validate_tests_count(v: String) -> Result<(), String> { - match v.parse::() { - Ok(_) => Ok(()), - Err(_) => Err(String::from( - "Tests count could not be converted to a usize.", - )), - } -} - -// Validate CLI argument input for fuzzed headers output path. -fn validate_path(v: String) -> Result<(), String> { - match Path::new(&v).is_dir() { - true => Ok(()), - false => Err(String::from("Provided directory path does not exist.")), - } -} - -fn main() { - let matches = App::new("quickchecking") - .version("0.2.0") - .about( - "Bindgen property tests with quickcheck. \ - Generate random valid C code and pass it to the \ - csmith/predicate.py script", - ) - .arg( - Arg::with_name("path") - .short("p") - .long("path") - .value_name("PATH") - .help( - "Optional. Preserve generated headers for inspection, \ - provide directory path for header output. [default: None] ", - ) - .takes_value(true) - .validator(validate_path), - ) - .arg( - Arg::with_name("range") - .short("r") - .long("range") - .value_name("RANGE") - .help( - "Sets the range quickcheck uses during generation. \ - Corresponds to things like arbitrary usize and \ - arbitrary vector length. This number doesn't have \ - to grow much for execution time to increase \ - significantly.", - ) - .takes_value(true) - .default_value("32") - .validator(validate_generate_range), - ) - .arg( - Arg::with_name("count") - .short("c") - .long("count") - .value_name("COUNT") - .help( - "Count / number of tests to run. Running a fuzzed \ - header through the predicate.py script can take a \ - long time, especially if the generation range is \ - large. Increase this number if you're willing to \ - wait a while.", - ) - .takes_value(true) - .default_value("2") - .validator(validate_tests_count), - ) - .get_matches(); - - let output_path: Option<&str> = matches.value_of("path"); - let generate_range: usize = matches.value_of("range").unwrap().parse::().unwrap(); - let tests: usize = matches.value_of("count").unwrap().parse::().unwrap(); - - quickchecking::test_bindgen(generate_range, tests, output_path) -} diff --git a/tests/quickchecking/src/fuzzers.rs b/tests/quickchecking/src/fuzzers.rs deleted file mode 100644 index 2876da8628..0000000000 --- a/tests/quickchecking/src/fuzzers.rs +++ /dev/null @@ -1,637 +0,0 @@ -use quickcheck::{Arbitrary, Gen, StdGen}; -use std::fmt; -use rand::thread_rng; - -/// BaseTypeC is used in generation of C headers to represent the C language's -/// primitive types as well as `void*`. -#[derive(Debug, Clone)] -pub struct BaseTypeC { - /// String representation of C type. - pub def: String, -} - -/// TypeQualifierC is used in generation of C headers to represent qualifiers -/// such as `const`. -#[derive(Debug, Clone)] -pub struct TypeQualifierC { - /// String representation of C type qualifier. - pub def: String, -} - -/// PointerLevelC is used in generation of C headers to represent number of -/// `*` for pointer types. -#[derive(Debug, Clone)] -pub struct PointerLevelC { - /// String representation of C declaration's pointer level. - pub def: String, -} - -/// ArrayDimensionC is used in generation of C headers to represent number of -/// `[]` used to define array types. -#[derive(Debug, Clone)] -pub struct ArrayDimensionC { - /// String representation of C declaration's array dimension. - pub def: String, -} - -/// BasicTypeDeclarationC is used in generation of C headers to represent -/// declarations outside of function pointers that take the form -/// `BaseTypeC` + `TypeQualifierC` + `PointerLevelC` + `ident_id`. -#[derive(Debug, Clone)] -pub struct BasicTypeDeclarationC { - /// The declaration's base type, i.e. `int`. - pub type_name: BaseTypeC, - /// The declaration's type qualifier, i.e. `const`. - pub type_qualifier: TypeQualifierC, - /// The declaration's pointer level, i.e. `***`. - pub pointer_level: PointerLevelC, - /// The declaration's array dimension, i.e. [][][]. - pub array_dimension: ArrayDimensionC, - /// The declaration's identifier, i.e. ident_N. - pub ident_id: String, -} - -/// StructDeclarationC is used in generation of C headers to represent the -/// definition of a struct type. -#[derive(Debug, Clone)] -pub struct StructDeclarationC { - /// The declaration's fields. - pub fields: DeclarationListC, - /// The declaration's array dimension, i.e. [][][]. - pub array_dimension: ArrayDimensionC, - /// The declaration's identifier, i.e. struct_N. - pub ident_id: String, -} - -/// UnionDeclarationC is used in generation of C headers to represent the -/// definition of a union type. -#[derive(Debug, Clone)] -pub struct UnionDeclarationC { - /// The declaration's fields. - pub fields: DeclarationListC, - /// The declaration's array dimension, i.e. [][][]. - pub array_dimension: ArrayDimensionC, - /// The declaration's identifier, i.e. union_N. - pub ident_id: String, -} - -/// FunctionPointerDeclarationC is used in generation of C headers to represent -/// the definition of a function pointer type. -#[derive(Debug, Clone)] -pub struct FunctionPointerDeclarationC { - /// The function's type qualifier, i.e. `const`. - pub type_qualifier: TypeQualifierC, - /// The function's return type, i.e. `int`. - pub type_name: BaseTypeC, - /// The function's pointer level, i.e. `***`. - pub pointer_level: PointerLevelC, - /// The function's parameters. - pub params: ParameterListC, - /// The declaration's identifier, i.e. func_ptr_N. - pub ident_id: String, -} - -/// FunctionPrototypeC is used in generation of C headers to represent the -/// definition of a function prototype. -#[derive(Debug, Clone)] -pub struct FunctionPrototypeC { - /// The function's type qualifier, i.e. `const`. - pub type_qualifier: TypeQualifierC, - /// The function's return type, i.e. `int`. - pub type_name: BaseTypeC, - /// The function's pointer level, i.e. `***`. - pub pointer_level: PointerLevelC, - /// The function's parameters. - pub params: ParameterListC, - /// The prototype's identifier, i.e. `func_N`. - pub ident_id: String, -} - -/// ParameterC is used in generation of C headers to represent the -/// definition function parameters. -#[derive(Debug, Clone)] -pub struct ParameterC { - /// The parameter's type qualifier, i.e. `const`. - pub type_qualifier: TypeQualifierC, - /// The parameter's base type, i.e. `int`. - pub type_name: BaseTypeC, - /// The parameter's pointer level, i.e. `***`. - pub pointer_level: PointerLevelC, -} - -/// ParameterListC is used in generation of C headers to represent a list of -/// definitions of function parameters. -#[derive(Debug, Clone)] -pub struct ParameterListC { - /// Parameters that define a C function signature. - pub params: Vec, -} - -/// DeclarationC is used in generation of C headers to represent all supported -/// C type declarations allowed in the generated header. -#[derive(Debug, Clone)] -pub enum DeclarationC { - /// Function prototype declaration kind. - FunctionDecl(FunctionPrototypeC), - /// Function pointer declaration kind. - FunctionPtrDecl(FunctionPointerDeclarationC), - /// Struct declaration kind. - StructDecl(StructDeclarationC), - /// Union declaration kind. - UnionDecl(UnionDeclarationC), - /// Basic type declaration kind. - VariableDecl(BasicTypeDeclarationC), -} - -/// DeclarationListC is used in generation of C headers to represent a list of -/// declarations. -#[derive(Debug, Clone)] -pub struct DeclarationListC { - /// Grouping of C declarations. - pub decls: Vec, -} - -/// HeaderC is used in generation of C headers to represent a collection of -/// declarations. -#[derive(Clone)] -pub struct HeaderC { - /// The header's declarations. - pub def: DeclarationListC, -} - -/// MakeUnique is used in generation of C headers to make declaration -/// identifiers unique by incorporating the `stamp` parameter into it's name. -trait MakeUnique { - fn make_unique(&mut self, stamp: usize); -} - -/// MakeUnique is used in generation of C headers to make DeclarationC -/// identifiers unique. -impl MakeUnique for DeclarationC { - fn make_unique(&mut self, stamp: usize) { - match *self { - DeclarationC::FunctionDecl(ref mut d) => d.make_unique(stamp), - DeclarationC::FunctionPtrDecl(ref mut d) => d.make_unique(stamp), - DeclarationC::StructDecl(ref mut d) => d.make_unique(stamp), - DeclarationC::UnionDecl(ref mut d) => d.make_unique(stamp), - DeclarationC::VariableDecl(ref mut d) => d.make_unique(stamp), - } - } -} - -/// A qucickcheck trait for describing how DeclarationC types can be -/// randomly generated and shrunk. -impl Arbitrary for DeclarationC { - fn arbitrary(g: &mut G) -> DeclarationC { - match g.gen_range(0, 5) { - 0 => DeclarationC::FunctionDecl(FunctionPrototypeC::arbitrary(g)), - 1 => DeclarationC::FunctionPtrDecl(FunctionPointerDeclarationC::arbitrary(g)), - 2 => DeclarationC::StructDecl(StructDeclarationC::arbitrary(g)), - 3 => DeclarationC::UnionDecl(UnionDeclarationC::arbitrary(g)), - 4 => DeclarationC::VariableDecl(BasicTypeDeclarationC::arbitrary(g)), - _ => unreachable!(), - } - } -} - -/// Enables to string and format for DeclarationC types. -impl fmt::Display for DeclarationC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - DeclarationC::FunctionPtrDecl(ref d) => write!(f, "{}", d), - DeclarationC::StructDecl(ref d) => write!(f, "{}", d), - DeclarationC::UnionDecl(ref d) => write!(f, "{}", d), - DeclarationC::VariableDecl(ref d) => write!(f, "{}", d), - DeclarationC::FunctionDecl(ref d) => write!(f, "{}", d), - } - } -} - -/// A qucickcheck trait for describing how DeclarationListC types can be -/// randomly generated and shrunk. -impl Arbitrary for DeclarationListC { - fn arbitrary(g: &mut G) -> DeclarationListC { - DeclarationListC { - decls: Arbitrary::arbitrary(g), - } - } -} - -/// Enables to string and format for DeclarationListC types. -impl fmt::Display for DeclarationListC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut display = String::new(); - for decl in &self.decls { - display += &format!("{}", decl); - } - write!(f, "{}", display) - } -} - -/// A qucickcheck trait for describing how BaseTypeC types can be -/// randomly generated and shrunk. -impl Arbitrary for BaseTypeC { - fn arbitrary(g: &mut G) -> BaseTypeC { - // Special case `long double` until issue #550 is resolved. - let base_type = vec![ - "char", - "signed char", - "unsigned char", - "short", - "short int", - "signed short", - "signed short int", - "unsigned short", - "unsigned short int", - "int", - "signed", - "signed int", - "unsigned", - "unsigned int", - "long", - "long int", - "signed long", - "signed long int", - "unsigned long", - "unsigned long int", - "long long", - "long long int", - "signed long long", - "signed long long int", - "unsigned long long", - "unsigned long long int", - "float", - "double", - #[cfg(feature = "long-doubles")] - "long double", - "void*", - ]; - BaseTypeC { - def: String::from(*g.choose(&base_type).unwrap()), - } - } -} - -/// Enables to string and format for BaseTypeC types, -impl fmt::Display for BaseTypeC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.def) - } -} - -/// A qucickcheck trait for describing how TypeQualifierC types can be -/// randomly generated and shrunk. -impl Arbitrary for TypeQualifierC { - fn arbitrary(g: &mut G) -> TypeQualifierC { - let qualifier = vec!["const", ""]; - TypeQualifierC { - def: String::from(*g.choose(&qualifier).unwrap()), - } - } -} - -/// Enables to string and format for TypeQualifierC types. -impl fmt::Display for TypeQualifierC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.def) - } -} - -/// A qucickcheck trait for describing how PointerLevelC types can be -/// randomly generated and shrunk. -impl Arbitrary for PointerLevelC { - fn arbitrary(g: &mut G) -> PointerLevelC { - PointerLevelC { - // 16 is an arbitrary "not too big" number for capping pointer level. - def: (0..g.gen_range(0, 16)).map(|_| "*").collect::(), - } - } -} - -/// Enables to string and format for PointerLevelC types. -impl fmt::Display for PointerLevelC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.def) - } -} - -/// A qucickcheck trait for describing how ArrayDimensionC types can be -/// randomly generated and shrunk. -impl Arbitrary for ArrayDimensionC { - fn arbitrary(g: &mut G) -> ArrayDimensionC { - // Keep these small, clang complains when they get too big. - let dimensions = g.gen_range(0, 5); - let mut def = String::new(); - - let lower_bound; - if cfg!(feature = "zero-sized-arrays") { - lower_bound = 0; - } else { - lower_bound = 1; - } - - for _ in 1..dimensions { - // 16 is an arbitrary "not too big" number for capping array size. - def += &format!("[{}]", g.gen_range(lower_bound, 16)); - } - ArrayDimensionC { def } - } -} - -/// Enables to string and format for ArrayDimensionC types. -impl fmt::Display for ArrayDimensionC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.def) - } -} - -/// MakeUnique is used in generation of C headers to make BasicTypeDeclarationC -/// identifiers unique. -impl MakeUnique for BasicTypeDeclarationC { - fn make_unique(&mut self, stamp: usize) { - self.ident_id += &format!("_{}", stamp); - } -} - -/// A qucickcheck trait for describing how BasicTypeDeclarationC types can be -/// randomly generated and shrunk. -impl Arbitrary for BasicTypeDeclarationC { - fn arbitrary(g: &mut G) -> BasicTypeDeclarationC { - BasicTypeDeclarationC { - type_qualifier: Arbitrary::arbitrary(g), - type_name: Arbitrary::arbitrary(g), - pointer_level: Arbitrary::arbitrary(g), - array_dimension: Arbitrary::arbitrary(g), - ident_id: format!("{}", usize::arbitrary(g)), - } - } -} - -/// Enables to string and format for BasicTypeDeclarationC types. -impl fmt::Display for BasicTypeDeclarationC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{} {} {} ident_{}{};", - self.type_qualifier, - self.type_name, - self.pointer_level, - self.ident_id, - self.array_dimension - ) - } -} - -/// MakeUnique is used in generation of C headers to make StructDeclarationC -/// identifiers unique. -impl MakeUnique for StructDeclarationC { - fn make_unique(&mut self, stamp: usize) { - self.ident_id += &format!("_{}", stamp); - } -} - -/// A qucickcheck trait for describing how StructDeclarationC types can be -/// randomly generated and shrunk. -impl Arbitrary for StructDeclarationC { - fn arbitrary(g: &mut G) -> StructDeclarationC { - // Reduce generator size as a method of putting a bound on recursion. - // When size < 1 the empty list is generated. - let reduced_size: usize = (g.size() / 2) as usize + 1; - let mut decl_list: DeclarationListC = - Arbitrary::arbitrary(&mut StdGen::new(thread_rng(), reduced_size)); - let mut fields: DeclarationListC = DeclarationListC { decls: vec![] }; - - for (i, decl) in decl_list.decls.iter_mut().enumerate() { - match *decl { - DeclarationC::FunctionDecl(_) => {} - ref mut decl => { - decl.make_unique(i); - fields.decls.push(decl.clone()); - } - } - } - - StructDeclarationC { - fields, - ident_id: format!("{}", usize::arbitrary(g)), - array_dimension: Arbitrary::arbitrary(g), - } - } -} - -/// Enables to string and format for StructDeclarationC types. -impl fmt::Display for StructDeclarationC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "struct {{ {} }} struct_{}{};", - self.fields, - self.ident_id, - self.array_dimension - ) - } -} - -/// MakeUnique is used in generation of C headers to make UnionDeclarationC -/// identifiers unique. -impl MakeUnique for UnionDeclarationC { - fn make_unique(&mut self, stamp: usize) { - self.ident_id += &format!("_{}", stamp); - } -} - -/// A qucickcheck trait for describing how UnionDeclarationC types can be -/// randomly generated and shrunk. -impl Arbitrary for UnionDeclarationC { - fn arbitrary(g: &mut G) -> UnionDeclarationC { - // Reduce generator size as a method of putting a bound on recursion. - // When size < 1 the empty list is generated. - let reduced_size: usize = (g.size() / 2) as usize + 1; - let mut decl_list: DeclarationListC = - Arbitrary::arbitrary(&mut StdGen::new(thread_rng(), reduced_size)); - let mut fields: DeclarationListC = DeclarationListC { decls: vec![] }; - - for (i, decl) in decl_list.decls.iter_mut().enumerate() { - match *decl { - DeclarationC::FunctionDecl(_) => {} - ref mut decl => { - decl.make_unique(i); - fields.decls.push(decl.clone()); - } - } - } - - UnionDeclarationC { - fields, - ident_id: format!("{}", usize::arbitrary(g)), - array_dimension: Arbitrary::arbitrary(g), - } - } -} - -/// Enables to string and format for UnionDeclarationC types. -impl fmt::Display for UnionDeclarationC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "union {{ {} }} union_{}{};", - self.fields, - self.ident_id, - self.array_dimension - ) - } -} - -/// MakeUnique is used in generation of C headers to make -/// FunctionPointerDeclarationC identifiers unique. -impl MakeUnique for FunctionPointerDeclarationC { - fn make_unique(&mut self, stamp: usize) { - self.ident_id += &format!("_{}", stamp); - } -} - -/// A qucickcheck trait for describing how FunctionPointerDeclarationC types can -/// be randomly generated and shrunk. -impl Arbitrary for FunctionPointerDeclarationC { - fn arbitrary(g: &mut G) -> FunctionPointerDeclarationC { - FunctionPointerDeclarationC { - type_qualifier: Arbitrary::arbitrary(g), - type_name: Arbitrary::arbitrary(g), - pointer_level: Arbitrary::arbitrary(g), - params: Arbitrary::arbitrary(g), - ident_id: format!("{}", usize::arbitrary(g)), - } - } -} - -/// Enables to string and format for FunctionPointerDeclarationC types. -impl fmt::Display for FunctionPointerDeclarationC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{} {} {} (*func_ptr_{})({});", - self.type_qualifier, - self.type_name, - self.pointer_level, - self.ident_id, - self.params - ) - } -} - -/// MakeUnique is used in generation of C headers to make FunctionPrototypeC -/// identifiers unique. -impl MakeUnique for FunctionPrototypeC { - fn make_unique(&mut self, stamp: usize) { - self.ident_id += &format!("_{}", stamp); - } -} - -/// A qucickcheck trait for describing how FunctionPrototypeC types can be -/// randomly generated and shrunk. -impl Arbitrary for FunctionPrototypeC { - fn arbitrary(g: &mut G) -> FunctionPrototypeC { - FunctionPrototypeC { - type_qualifier: Arbitrary::arbitrary(g), - type_name: Arbitrary::arbitrary(g), - pointer_level: Arbitrary::arbitrary(g), - params: Arbitrary::arbitrary(g), - ident_id: format!("{}", usize::arbitrary(g)), - } - } -} - -/// Enables to string and format for FunctionPrototypeC types. -impl fmt::Display for FunctionPrototypeC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{} {} {} func_{}({});", - self.type_qualifier, - self.type_name, - self.pointer_level, - self.ident_id, - self.params - ) - } -} - -/// A qucickcheck trait for describing how ParameterC types can be -/// randomly generated and shrunk. -impl Arbitrary for ParameterC { - fn arbitrary(g: &mut G) -> ParameterC { - ParameterC { - type_qualifier: Arbitrary::arbitrary(g), - type_name: Arbitrary::arbitrary(g), - pointer_level: Arbitrary::arbitrary(g), - } - } -} - -/// Enables to string and format for ParameterC types. -impl fmt::Display for ParameterC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{} {} {}", - self.type_qualifier, - self.type_name, - self.pointer_level - ) - } -} - -/// A qucickcheck trait for describing how ParameterListC types can be -/// randomly generated and shrunk. -impl Arbitrary for ParameterListC { - fn arbitrary(g: &mut G) -> ParameterListC { - ParameterListC { - params: Arbitrary::arbitrary(g), - } - } -} - -/// Enables to string and format for ParameterListC types. -impl fmt::Display for ParameterListC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut display = String::new(); - for (i, p) in self.params.iter().enumerate() { - match i { - 0 => display += &format!("{}", p), - _ => display += &format!(",{}", p), - } - } - write!(f, "{}", display) - } -} - -/// A qucickcheck trait for describing how HeaderC types can be -/// randomly generated and shrunk. -impl Arbitrary for HeaderC { - fn arbitrary(g: &mut G) -> HeaderC { - let mut decl_list: DeclarationListC = Arbitrary::arbitrary(g); - for (i, decl) in decl_list.decls.iter_mut().enumerate() { - decl.make_unique(i); - } - HeaderC { def: decl_list } - } -} - -/// Enables to string and format for HeaderC types. -impl fmt::Display for HeaderC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut display = String::new(); - for decl in &self.def.decls { - display += &format!("{}", decl); - } - write!(f, "{}", display) - } -} - -/// Use Display trait for Debug so that any failing property tests report -/// generated C code rather than the data structures that contain it. -impl fmt::Debug for HeaderC { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} diff --git a/tests/quickchecking/src/lib.rs b/tests/quickchecking/src/lib.rs deleted file mode 100644 index d8633dfb92..0000000000 --- a/tests/quickchecking/src/lib.rs +++ /dev/null @@ -1,126 +0,0 @@ -//! A library to generate __fuzzed__ C headers for use with `quickcheck` -//! -//! ## Example -//! -//! ```rust -//! extern crate quickcheck; -//! extern crate quickchecking; -//! extern crate rand; -//! use quickcheck::{Arbitrary, Gen, StdGen}; -//! use quickchecking::fuzzers; -//! use rand::thread_rng; -//! -//! fn main() { -//! let generate_range: usize = 10; // Determines things like the length of -//! // arbitrary vectors generated. -//! let header = fuzzers::HeaderC::arbitrary( -//! &mut StdGen::new(thread_rng(), generate_range)); -//! println!("{}", header); -//! } -//! ``` -//! -#![deny(missing_docs)] -#[macro_use] -extern crate lazy_static; -extern crate quickcheck; -extern crate rand; -extern crate tempdir; - -use std::sync::Mutex; -use quickcheck::{QuickCheck, StdGen, TestResult}; -use std::fs::File; -use std::io::Write; -use tempdir::TempDir; -use std::process::{Command, Output}; -use std::path::PathBuf; -use std::error::Error; -use rand::thread_rng; - -/// Contains definitions of and impls for types used to fuzz C declarations. -pub mod fuzzers; - -// Global singleton, manages context across tests. For now that context is -// only the output_path for inspecting fuzzed headers (if specified). -struct Context { - output_path: Option, -} - -// Initialize global context. -lazy_static! { - static ref CONTEXT: Mutex = Mutex::new(Context { output_path: None }); -} - -// Passes fuzzed header to the `csmith-fuzzing/predicate.py` script, returns -// output of the associated command. -fn run_predicate_script(header: fuzzers::HeaderC) -> Result> { - let dir = TempDir::new("bindgen_prop")?; - let header_path = dir.path().join("prop_test.h"); - - let mut header_file = File::create(&header_path)?; - header_file.write_all(header.to_string().as_bytes())?; - header_file.sync_all()?; - - let header_path_string; - match header_path.into_os_string().into_string() { - Ok(s) => header_path_string = s, - Err(_) => return Err(From::from("error converting path into String")), - } - - let mut predicate_script_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - predicate_script_path.push("../../csmith-fuzzing/predicate.py"); - - let predicate_script_path_string; - match predicate_script_path.into_os_string().into_string() { - Ok(s) => predicate_script_path_string = s, - Err(_) => return Err(From::from("error converting path into String")), - } - - // Copy generated temp files to output_path directory for inspection. - // If `None`, output path not specified, don't copy. - match CONTEXT.lock().unwrap().output_path { - Some(ref path) => { - Command::new("cp") - .arg("-a") - .arg(&dir.path().to_str().unwrap()) - .arg(&path) - .output()?; - } - None => {} - } - - Ok(Command::new(&predicate_script_path_string) - .arg(&header_path_string) - .output()?) -} - -// Generatable property. Pass generated headers off to run through the -// `csmith-fuzzing/predicate.py` script. Success is measured by the success -// status of that command. -fn bindgen_prop(header: fuzzers::HeaderC) -> TestResult { - match run_predicate_script(header) { - Ok(o) => return TestResult::from_bool(o.status.success()), - Err(e) => { - println!("{:?}", e); - return TestResult::from_bool(false); - } - } -} - -/// Instantiate a Quickcheck object and use it to run property tests using -/// fuzzed C headers generated with types defined in the `fuzzers` module. -/// Success/Failure is dictated by the result of passing the fuzzed headers -/// to the `csmith-fuzzing/predicate.py` script. -pub fn test_bindgen(generate_range: usize, tests: usize, output_path: Option<&str>) { - match output_path { - Some(path) => { - CONTEXT.lock().unwrap().output_path = - Some(String::from(PathBuf::from(path).to_str().unwrap())); - } - None => {} // Path not specified, don't provide output. - } - - QuickCheck::new() - .tests(tests) - .gen(StdGen::new(thread_rng(), generate_range)) - .quickcheck(bindgen_prop as fn(fuzzers::HeaderC) -> TestResult) -} diff --git a/tests/quickchecking/tests/fuzzed-c-headers.rs b/tests/quickchecking/tests/fuzzed-c-headers.rs deleted file mode 100644 index 6b58d24b23..0000000000 --- a/tests/quickchecking/tests/fuzzed-c-headers.rs +++ /dev/null @@ -1,95 +0,0 @@ - -extern crate quickcheck; -extern crate quickchecking; -extern crate rand; - -use quickchecking::fuzzers::{ArrayDimensionC, BaseTypeC, BasicTypeDeclarationC, DeclarationC, - DeclarationListC, FunctionPointerDeclarationC, FunctionPrototypeC, - HeaderC, ParameterC, ParameterListC, PointerLevelC, - StructDeclarationC, TypeQualifierC, UnionDeclarationC}; -use quickcheck::{Arbitrary, StdGen}; -use rand::thread_rng; - -#[test] -fn test_declaraion_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: DeclarationC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_declaraion_list_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: DeclarationListC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_base_type_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: BaseTypeC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_type_qualifier_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: TypeQualifierC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_pointer_level_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: PointerLevelC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_array_dimension_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: ArrayDimensionC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_basic_type_declaration_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: BasicTypeDeclarationC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_struct_declaration_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: StructDeclarationC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_union_declaration_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: UnionDeclarationC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_function_pointer_declaration_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: FunctionPointerDeclarationC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_function_prototype_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: FunctionPrototypeC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_parameter_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: ParameterC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_parameter_list_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: ParameterListC = Arbitrary::arbitrary(gen); -} - -#[test] -fn test_header_c_does_not_panic() { - let ref mut gen = StdGen::new(thread_rng(), 50); - let _: HeaderC = Arbitrary::arbitrary(gen); -} diff --git a/tests/rustfmt.toml b/tests/rustfmt.toml deleted file mode 100644 index 80a6663b9c..0000000000 --- a/tests/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -# Intentionally left blank. diff --git a/tests/stylo_sanity.rs b/tests/stylo_sanity.rs deleted file mode 100755 index d2d2e841b5..0000000000 --- a/tests/stylo_sanity.rs +++ /dev/null @@ -1,555 +0,0 @@ -// Don't want to copy that nasty `cfg` below... -#[allow(unused_extern_crates)] -extern crate bindgen; - -/// A sanity test that we can generate bindings for Stylo. -/// -/// We don't assert on expected output because its just too big. The output will -/// change too often, and it won't be clear what is going on at a glance, unlike -/// the other tests with smaller input headers. -/// -/// This test is relatively slow, so we also only run it in release mode. -/// -/// Finally, uncomment the `panic!` at the bottom of the test to get logs timing -/// how long bindings generation takes for Stylo. Stylo bindings generation -/// takes too long to be a proper `#[bench]`. -#[test] -#[cfg(not(any(debug_assertions, - feature = "testing_only_extra_assertions", - feature = "testing_only_libclang_3_8")))] -#[cfg(any(feature = "testing_only_libclang_3_9", - feature = "testing_only_libclang_4"))] -fn sanity_check_can_generate_stylo_bindings() { - use std::time::Instant; - - let then = Instant::now(); - - bindgen::builder() - .time_phases(true) - .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/stylo.hpp")) - .whitelist_function("Servo_.*") - .whitelist_function("Gecko_.*") - .blacklist_type("nsACString_internal") - .blacklist_type("nsAString_internal") - .blacklist_type("mozilla::css::URLValue") - .blacklist_type("RawGeckoAnimationPropertySegment") - .blacklist_type("RawGeckoComputedTiming") - .blacklist_type("RawGeckoDocument") - .blacklist_type("RawGeckoElement") - .blacklist_type("RawGeckoKeyframeList") - .blacklist_type("RawGeckoComputedKeyframeValuesList") - .blacklist_type("RawGeckoFontFaceRuleList") - .blacklist_type("RawGeckoNode") - .blacklist_type("RawGeckoAnimationValueList") - .blacklist_type("RawServoAnimationValue") - .blacklist_type("RawServoAnimationValueMap") - .blacklist_type("RawServoDeclarationBlock") - .blacklist_type("RawGeckoPresContext") - .blacklist_type("RawGeckoPresContextOwned") - .blacklist_type("RawGeckoStyleAnimationList") - .blacklist_type("RawGeckoURLExtraData") - .blacklist_type("RefPtr") - .blacklist_type("CSSPseudoClassType") - .blacklist_type("TraversalRootBehavior") - .blacklist_type("ComputedTimingFunction_BeforeFlag") - .blacklist_type("FontFamilyList") - .blacklist_type("FontFamilyType") - .blacklist_type("Keyframe") - .blacklist_type("ServoBundledURI") - .blacklist_type("ServoElementSnapshot") - .blacklist_type("SheetParsingMode") - .blacklist_type("StyleBasicShape") - .blacklist_type("StyleBasicShapeType") - .blacklist_type("StyleShapeSource") - .blacklist_type("nsCSSFontFaceRule") - .blacklist_type("nsCSSKeyword") - .blacklist_type("nsCSSPropertyID") - .blacklist_type("nsCSSShadowArray") - .blacklist_type("nsCSSUnit") - .blacklist_type("nsCSSValue") - .blacklist_type("nsCSSValueSharedList") - .blacklist_type("nsChangeHint") - .blacklist_type("nsCursorImage") - .blacklist_type("nsFont") - .blacklist_type("nsIAtom") - .blacklist_type("nsMediaFeature") - .blacklist_type("nsRestyleHint") - .blacklist_type("nsStyleBackground") - .blacklist_type("nsStyleBorder") - .blacklist_type("nsStyleColor") - .blacklist_type("nsStyleColumn") - .blacklist_type("nsStyleContent") - .blacklist_type("nsStyleContentData") - .blacklist_type("nsStyleContentType") - .blacklist_type("nsStyleContext") - .blacklist_type("nsStyleCoord") - .blacklist_type("nsStyleCoord_Calc") - .blacklist_type("nsStyleCoord_CalcValue") - .blacklist_type("nsStyleDisplay") - .blacklist_type("nsStyleEffects") - .blacklist_type("nsStyleFilter") - .blacklist_type("nsStyleFont") - .blacklist_type("nsStyleGradient") - .blacklist_type("nsStyleGradientStop") - .blacklist_type("nsStyleImage") - .blacklist_type("nsStyleImageLayers") - .blacklist_type("nsStyleImageLayers_Layer") - .blacklist_type("nsStyleImageLayers_LayerType") - .blacklist_type("nsStyleImageRequest") - .blacklist_type("nsStyleList") - .blacklist_type("nsStyleMargin") - .blacklist_type("nsStyleOutline") - .blacklist_type("nsStylePadding") - .blacklist_type("nsStylePosition") - .blacklist_type("nsStyleQuoteValues") - .blacklist_type("nsStyleSVG") - .blacklist_type("nsStyleSVGPaint") - .blacklist_type("nsStyleSVGReset") - .blacklist_type("nsStyleTable") - .blacklist_type("nsStyleTableBorder") - .blacklist_type("nsStyleText") - .blacklist_type("nsStyleTextReset") - .blacklist_type("nsStyleUIReset") - .blacklist_type("nsStyleUnion") - .blacklist_type("nsStyleUnit") - .blacklist_type("nsStyleUserInterface") - .blacklist_type("nsStyleVariables") - .blacklist_type("nsStyleVisibility") - .blacklist_type("nsStyleXUL") - .blacklist_type("nsTimingFunction") - .blacklist_type("nscolor") - .blacklist_type("nscoord") - .blacklist_type("nsresult") - .blacklist_type("Loader") - .blacklist_type("ServoStyleSheet") - .blacklist_type("EffectCompositor_CascadeLevel") - .blacklist_type("UpdateAnimationsTasks") - .blacklist_type("nsTArrayBorrowed_uintptr_t") - .blacklist_type("ServoCssRulesStrong") - .blacklist_type("ServoCssRulesBorrowed") - .blacklist_type("ServoCssRulesBorrowedOrNull") - .blacklist_type("ServoCssRules") - .blacklist_type("RawServoStyleSheetStrong") - .blacklist_type("RawServoStyleSheetBorrowed") - .blacklist_type("RawServoStyleSheetBorrowedOrNull") - .blacklist_type("RawServoStyleSheet") - .blacklist_type("ServoComputedValuesStrong") - .blacklist_type("ServoComputedValuesBorrowed") - .blacklist_type("ServoComputedValuesBorrowedOrNull") - .blacklist_type("ServoComputedValues") - .blacklist_type("RawServoDeclarationBlockStrong") - .blacklist_type("RawServoDeclarationBlockBorrowed") - .blacklist_type("RawServoDeclarationBlockBorrowedOrNull") - .blacklist_type("RawServoStyleRuleStrong") - .blacklist_type("RawServoStyleRuleBorrowed") - .blacklist_type("RawServoStyleRuleBorrowedOrNull") - .blacklist_type("RawServoStyleRule") - .blacklist_type("RawServoImportRuleStrong") - .blacklist_type("RawServoImportRuleBorrowed") - .blacklist_type("RawServoImportRuleBorrowedOrNull") - .blacklist_type("RawServoImportRule") - .blacklist_type("RawServoAnimationValueStrong") - .blacklist_type("RawServoAnimationValueBorrowed") - .blacklist_type("RawServoAnimationValueBorrowedOrNull") - .blacklist_type("RawServoAnimationValueMapStrong") - .blacklist_type("RawServoAnimationValueMapBorrowed") - .blacklist_type("RawServoAnimationValueMapBorrowedOrNull") - .blacklist_type("RawServoMediaListStrong") - .blacklist_type("RawServoMediaListBorrowed") - .blacklist_type("RawServoMediaListBorrowedOrNull") - .blacklist_type("RawServoMediaList") - .blacklist_type("RawServoMediaRuleStrong") - .blacklist_type("RawServoMediaRuleBorrowed") - .blacklist_type("RawServoMediaRuleBorrowedOrNull") - .blacklist_type("RawServoMediaRule") - .blacklist_type("RawServoNamespaceRuleStrong") - .blacklist_type("RawServoNamespaceRuleBorrowed") - .blacklist_type("RawServoNamespaceRuleBorrowedOrNull") - .blacklist_type("RawServoNamespaceRule") - .blacklist_type("RawServoStyleSetOwned") - .blacklist_type("RawServoStyleSetOwnedOrNull") - .blacklist_type("RawServoStyleSetBorrowed") - .blacklist_type("RawServoStyleSetBorrowedOrNull") - .blacklist_type("RawServoStyleSetBorrowedMut") - .blacklist_type("RawServoStyleSetBorrowedMutOrNull") - .blacklist_type("RawServoStyleSet") - .blacklist_type("StyleChildrenIteratorOwned") - .blacklist_type("StyleChildrenIteratorOwnedOrNull") - .blacklist_type("StyleChildrenIteratorBorrowed") - .blacklist_type("StyleChildrenIteratorBorrowedOrNull") - .blacklist_type("StyleChildrenIteratorBorrowedMut") - .blacklist_type("StyleChildrenIteratorBorrowedMutOrNull") - .blacklist_type("StyleChildrenIterator") - .blacklist_type("ServoElementSnapshotOwned") - .blacklist_type("ServoElementSnapshotOwnedOrNull") - .blacklist_type("ServoElementSnapshotBorrowed") - .blacklist_type("ServoElementSnapshotBorrowedOrNull") - .blacklist_type("ServoElementSnapshotBorrowedMut") - .blacklist_type("ServoElementSnapshotBorrowedMutOrNull") - .blacklist_type("RawGeckoNodeBorrowed") - .blacklist_type("RawGeckoNodeBorrowedOrNull") - .blacklist_type("RawGeckoElementBorrowed") - .blacklist_type("RawGeckoElementBorrowedOrNull") - .blacklist_type("RawGeckoDocumentBorrowed") - .blacklist_type("RawGeckoDocumentBorrowedOrNull") - .blacklist_type("RawServoDeclarationBlockStrongBorrowed") - .blacklist_type("RawServoDeclarationBlockStrongBorrowedOrNull") - .blacklist_type("RawGeckoPresContextBorrowed") - .blacklist_type("RawGeckoPresContextBorrowedOrNull") - .blacklist_type("RawGeckoStyleAnimationListBorrowed") - .blacklist_type("RawGeckoStyleAnimationListBorrowedOrNull") - .blacklist_type("nsCSSValueBorrowed") - .blacklist_type("nsCSSValueBorrowedOrNull") - .blacklist_type("nsCSSValueBorrowedMut") - .blacklist_type("nsCSSValueBorrowedMutOrNull") - .blacklist_type("nsTimingFunctionBorrowed") - .blacklist_type("nsTimingFunctionBorrowedOrNull") - .blacklist_type("nsTimingFunctionBorrowedMut") - .blacklist_type("nsTimingFunctionBorrowedMutOrNull") - .blacklist_type("RawGeckoAnimationPropertySegmentBorrowed") - .blacklist_type("RawGeckoAnimationPropertySegmentBorrowedOrNull") - .blacklist_type("RawGeckoAnimationPropertySegmentBorrowedMut") - .blacklist_type("RawGeckoAnimationPropertySegmentBorrowedMutOrNull") - .blacklist_type("RawGeckoAnimationValueListBorrowed") - .blacklist_type("RawGeckoAnimationValueListBorrowedOrNull") - .blacklist_type("RawGeckoAnimationValueListBorrowedMut") - .blacklist_type("RawGeckoAnimationValueListBorrowedMutOrNull") - .blacklist_type("RawGeckoComputedTimingBorrowed") - .blacklist_type("RawGeckoComputedTimingBorrowedOrNull") - .blacklist_type("RawGeckoComputedTimingBorrowedMut") - .blacklist_type("RawGeckoComputedTimingBorrowedMutOrNull") - .blacklist_type("RawGeckoKeyframeListBorrowed") - .blacklist_type("RawGeckoKeyframeListBorrowedOrNull") - .blacklist_type("RawGeckoKeyframeListBorrowedMut") - .blacklist_type("RawGeckoKeyframeListBorrowedMutOrNull") - .blacklist_type("RawGeckoComputedKeyframeValuesListBorrowed") - .blacklist_type("RawGeckoComputedKeyframeValuesListBorrowedOrNull") - .blacklist_type("RawGeckoComputedKeyframeValuesListBorrowedMut") - .blacklist_type("RawGeckoComputedKeyframeValuesListBorrowedMutOrNull") - .blacklist_type("RawGeckoFontFaceRuleListBorrowed") - .blacklist_type("RawGeckoFontFaceRuleListBorrowedOrNull") - .blacklist_type("RawGeckoFontFaceRuleListBorrowedMut") - .blacklist_type("RawGeckoFontFaceRuleListBorrowedMutOrNull") - .raw_line(r#"pub use nsstring::{nsACString, nsAString, nsString};"#) - .raw_line(r#"type nsACString_internal = nsACString;"#) - .raw_line(r#"type nsAString_internal = nsAString;"#) - .raw_line(r#"use gecko_bindings::structs::mozilla::css::URLValue;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoAnimationPropertySegment;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoComputedTiming;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoDocument;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoElement;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoKeyframeList;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoFontFaceRuleList;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoNode;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoAnimationValueList;"#) - .raw_line(r#"use gecko_bindings::structs::RawServoAnimationValue;"#) - .raw_line(r#"use gecko_bindings::structs::RawServoAnimationValueMap;"#) - .raw_line(r#"use gecko_bindings::structs::RawServoDeclarationBlock;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoPresContext;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoPresContextOwned;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoStyleAnimationList;"#) - .raw_line(r#"use gecko_bindings::structs::RawGeckoURLExtraData;"#) - .raw_line(r#"use gecko_bindings::structs::RefPtr;"#) - .raw_line(r#"use gecko_bindings::structs::CSSPseudoClassType;"#) - .raw_line(r#"use gecko_bindings::structs::TraversalRootBehavior;"#) - .raw_line(r#"use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;"#) - .raw_line(r#"use gecko_bindings::structs::FontFamilyList;"#) - .raw_line(r#"use gecko_bindings::structs::FontFamilyType;"#) - .raw_line(r#"use gecko_bindings::structs::Keyframe;"#) - .raw_line(r#"use gecko_bindings::structs::ServoBundledURI;"#) - .raw_line(r#"use gecko_bindings::structs::ServoElementSnapshot;"#) - .raw_line(r#"use gecko_bindings::structs::SheetParsingMode;"#) - .raw_line(r#"use gecko_bindings::structs::StyleBasicShape;"#) - .raw_line(r#"use gecko_bindings::structs::StyleBasicShapeType;"#) - .raw_line(r#"use gecko_bindings::structs::StyleShapeSource;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSFontFaceRule;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSKeyword;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSPropertyID;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSShadowArray;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSUnit;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSValue;"#) - .raw_line(r#"use gecko_bindings::structs::nsCSSValueSharedList;"#) - .raw_line(r#"use gecko_bindings::structs::nsChangeHint;"#) - .raw_line(r#"use gecko_bindings::structs::nsCursorImage;"#) - .raw_line(r#"use gecko_bindings::structs::nsFont;"#) - .raw_line(r#"use gecko_bindings::structs::nsIAtom;"#) - .raw_line(r#"use gecko_bindings::structs::nsMediaFeature;"#) - .raw_line(r#"use gecko_bindings::structs::nsRestyleHint;"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleBackground;"#) - .raw_line(r#"unsafe impl Send for nsStyleBackground {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleBackground {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleBorder;"#) - .raw_line(r#"unsafe impl Send for nsStyleBorder {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleBorder {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleColor;"#) - .raw_line(r#"unsafe impl Send for nsStyleColor {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleColor {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleColumn;"#) - .raw_line(r#"unsafe impl Send for nsStyleColumn {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleColumn {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleContent;"#) - .raw_line(r#"unsafe impl Send for nsStyleContent {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleContent {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleContentData;"#) - .raw_line(r#"unsafe impl Send for nsStyleContentData {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleContentData {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleContentType;"#) - .raw_line(r#"unsafe impl Send for nsStyleContentType {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleContentType {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleContext;"#) - .raw_line(r#"unsafe impl Send for nsStyleContext {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleContext {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleCoord;"#) - .raw_line(r#"unsafe impl Send for nsStyleCoord {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleCoord {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleCoord_Calc;"#) - .raw_line(r#"unsafe impl Send for nsStyleCoord_Calc {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleCoord_Calc {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleCoord_CalcValue;"#) - .raw_line(r#"unsafe impl Send for nsStyleCoord_CalcValue {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleCoord_CalcValue {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleDisplay;"#) - .raw_line(r#"unsafe impl Send for nsStyleDisplay {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleDisplay {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleEffects;"#) - .raw_line(r#"unsafe impl Send for nsStyleEffects {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleEffects {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleFilter;"#) - .raw_line(r#"unsafe impl Send for nsStyleFilter {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleFilter {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleFont;"#) - .raw_line(r#"unsafe impl Send for nsStyleFont {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleFont {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleGradient;"#) - .raw_line(r#"unsafe impl Send for nsStyleGradient {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleGradient {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleGradientStop;"#) - .raw_line(r#"unsafe impl Send for nsStyleGradientStop {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleGradientStop {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleImage;"#) - .raw_line(r#"unsafe impl Send for nsStyleImage {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleImage {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers;"#) - .raw_line(r#"unsafe impl Send for nsStyleImageLayers {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleImageLayers {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers_Layer;"#) - .raw_line(r#"unsafe impl Send for nsStyleImageLayers_Layer {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleImageLayers_Layer {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleImageLayers_LayerType;"#) - .raw_line(r#"unsafe impl Send for nsStyleImageLayers_LayerType {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleImageLayers_LayerType {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleImageRequest;"#) - .raw_line(r#"unsafe impl Send for nsStyleImageRequest {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleImageRequest {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleList;"#) - .raw_line(r#"unsafe impl Send for nsStyleList {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleList {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleMargin;"#) - .raw_line(r#"unsafe impl Send for nsStyleMargin {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleMargin {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleOutline;"#) - .raw_line(r#"unsafe impl Send for nsStyleOutline {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleOutline {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStylePadding;"#) - .raw_line(r#"unsafe impl Send for nsStylePadding {}"#) - .raw_line(r#"unsafe impl Sync for nsStylePadding {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStylePosition;"#) - .raw_line(r#"unsafe impl Send for nsStylePosition {}"#) - .raw_line(r#"unsafe impl Sync for nsStylePosition {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleQuoteValues;"#) - .raw_line(r#"unsafe impl Send for nsStyleQuoteValues {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleQuoteValues {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleSVG;"#) - .raw_line(r#"unsafe impl Send for nsStyleSVG {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleSVG {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleSVGPaint;"#) - .raw_line(r#"unsafe impl Send for nsStyleSVGPaint {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleSVGPaint {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleSVGReset;"#) - .raw_line(r#"unsafe impl Send for nsStyleSVGReset {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleSVGReset {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleTable;"#) - .raw_line(r#"unsafe impl Send for nsStyleTable {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleTable {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleTableBorder;"#) - .raw_line(r#"unsafe impl Send for nsStyleTableBorder {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleTableBorder {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleText;"#) - .raw_line(r#"unsafe impl Send for nsStyleText {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleText {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleTextReset;"#) - .raw_line(r#"unsafe impl Send for nsStyleTextReset {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleTextReset {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleUIReset;"#) - .raw_line(r#"unsafe impl Send for nsStyleUIReset {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleUIReset {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleUnion;"#) - .raw_line(r#"unsafe impl Send for nsStyleUnion {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleUnion {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleUnit;"#) - .raw_line(r#"unsafe impl Send for nsStyleUnit {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleUnit {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleUserInterface;"#) - .raw_line(r#"unsafe impl Send for nsStyleUserInterface {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleUserInterface {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleVariables;"#) - .raw_line(r#"unsafe impl Send for nsStyleVariables {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleVariables {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleVisibility;"#) - .raw_line(r#"unsafe impl Send for nsStyleVisibility {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleVisibility {}"#) - .raw_line(r#"use gecko_bindings::structs::nsStyleXUL;"#) - .raw_line(r#"unsafe impl Send for nsStyleXUL {}"#) - .raw_line(r#"unsafe impl Sync for nsStyleXUL {}"#) - .raw_line(r#"use gecko_bindings::structs::nsTimingFunction;"#) - .raw_line(r#"use gecko_bindings::structs::nscolor;"#) - .raw_line(r#"use gecko_bindings::structs::nscoord;"#) - .raw_line(r#"use gecko_bindings::structs::nsresult;"#) - .raw_line(r#"use gecko_bindings::structs::Loader;"#) - .raw_line(r#"use gecko_bindings::structs::ServoStyleSheet;"#) - .raw_line(r#"use gecko_bindings::structs::EffectCompositor_CascadeLevel;"#) - .raw_line(r#"use gecko_bindings::structs::UpdateAnimationsTasks;"#) - .raw_line(r#"pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray;"#) - .raw_line(r#"pub type ServoCssRulesStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;"#) - .raw_line(r#"pub type ServoCssRulesBorrowedOrNull<'a> = Option<&'a ServoCssRules>;"#) - .raw_line(r#"enum ServoCssRulesVoid { }"#) - .raw_line(r#"pub struct ServoCssRules(ServoCssRulesVoid);"#) - .raw_line(r#"pub type RawServoStyleSheetStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoStyleSheetBorrowed<'a> = &'a RawServoStyleSheet;"#) - .raw_line(r#"pub type RawServoStyleSheetBorrowedOrNull<'a> = Option<&'a RawServoStyleSheet>;"#) - .raw_line(r#"enum RawServoStyleSheetVoid { }"#) - .raw_line(r#"pub struct RawServoStyleSheet(RawServoStyleSheetVoid);"#) - .raw_line(r#"pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;"#) - .raw_line(r#"pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;"#) - .raw_line(r#"enum ServoComputedValuesVoid { }"#) - .raw_line(r#"pub struct ServoComputedValues(ServoComputedValuesVoid);"#) - .raw_line(r#"pub type RawServoDeclarationBlockStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoDeclarationBlockBorrowed<'a> = &'a RawServoDeclarationBlock;"#) - .raw_line(r#"pub type RawServoDeclarationBlockBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlock>;"#) - .raw_line(r#"pub type RawServoStyleRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoStyleRuleBorrowed<'a> = &'a RawServoStyleRule;"#) - .raw_line(r#"pub type RawServoStyleRuleBorrowedOrNull<'a> = Option<&'a RawServoStyleRule>;"#) - .raw_line(r#"enum RawServoStyleRuleVoid { }"#) - .raw_line(r#"pub struct RawServoStyleRule(RawServoStyleRuleVoid);"#) - .raw_line(r#"pub type RawServoImportRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoImportRuleBorrowed<'a> = &'a RawServoImportRule;"#) - .raw_line(r#"pub type RawServoImportRuleBorrowedOrNull<'a> = Option<&'a RawServoImportRule>;"#) - .raw_line(r#"enum RawServoImportRuleVoid { }"#) - .raw_line(r#"pub struct RawServoImportRule(RawServoImportRuleVoid);"#) - .raw_line(r#"pub type RawServoAnimationValueStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoAnimationValueBorrowed<'a> = &'a RawServoAnimationValue;"#) - .raw_line(r#"pub type RawServoAnimationValueBorrowedOrNull<'a> = Option<&'a RawServoAnimationValue>;"#) - .raw_line(r#"pub type RawServoAnimationValueMapStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoAnimationValueMapBorrowed<'a> = &'a RawServoAnimationValueMap;"#) - .raw_line(r#"pub type RawServoAnimationValueMapBorrowedOrNull<'a> = Option<&'a RawServoAnimationValueMap>;"#) - .raw_line(r#"pub type RawServoMediaListStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoMediaListBorrowed<'a> = &'a RawServoMediaList;"#) - .raw_line(r#"pub type RawServoMediaListBorrowedOrNull<'a> = Option<&'a RawServoMediaList>;"#) - .raw_line(r#"enum RawServoMediaListVoid { }"#) - .raw_line(r#"pub struct RawServoMediaList(RawServoMediaListVoid);"#) - .raw_line(r#"pub type RawServoMediaRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoMediaRuleBorrowed<'a> = &'a RawServoMediaRule;"#) - .raw_line(r#"pub type RawServoMediaRuleBorrowedOrNull<'a> = Option<&'a RawServoMediaRule>;"#) - .raw_line(r#"enum RawServoMediaRuleVoid { }"#) - .raw_line(r#"pub struct RawServoMediaRule(RawServoMediaRuleVoid);"#) - .raw_line(r#"pub type RawServoNamespaceRuleStrong = ::gecko_bindings::sugar::ownership::Strong;"#) - .raw_line(r#"pub type RawServoNamespaceRuleBorrowed<'a> = &'a RawServoNamespaceRule;"#) - .raw_line(r#"pub type RawServoNamespaceRuleBorrowedOrNull<'a> = Option<&'a RawServoNamespaceRule>;"#) - .raw_line(r#"enum RawServoNamespaceRuleVoid { }"#) - .raw_line(r#"pub struct RawServoNamespaceRule(RawServoNamespaceRuleVoid);"#) - .raw_line(r#"pub type RawServoStyleSetOwned = ::gecko_bindings::sugar::ownership::Owned;"#) - .raw_line(r#"pub type RawServoStyleSetOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) - .raw_line(r#"pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;"#) - .raw_line(r#"pub type RawServoStyleSetBorrowedOrNull<'a> = Option<&'a RawServoStyleSet>;"#) - .raw_line(r#"pub type RawServoStyleSetBorrowedMut<'a> = &'a mut RawServoStyleSet;"#) - .raw_line(r#"pub type RawServoStyleSetBorrowedMutOrNull<'a> = Option<&'a mut RawServoStyleSet>;"#) - .raw_line(r#"enum RawServoStyleSetVoid { }"#) - .raw_line(r#"pub struct RawServoStyleSet(RawServoStyleSetVoid);"#) - .raw_line(r#"pub type StyleChildrenIteratorOwned = ::gecko_bindings::sugar::ownership::Owned;"#) - .raw_line(r#"pub type StyleChildrenIteratorOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) - .raw_line(r#"pub type StyleChildrenIteratorBorrowed<'a> = &'a StyleChildrenIterator;"#) - .raw_line(r#"pub type StyleChildrenIteratorBorrowedOrNull<'a> = Option<&'a StyleChildrenIterator>;"#) - .raw_line(r#"pub type StyleChildrenIteratorBorrowedMut<'a> = &'a mut StyleChildrenIterator;"#) - .raw_line(r#"pub type StyleChildrenIteratorBorrowedMutOrNull<'a> = Option<&'a mut StyleChildrenIterator>;"#) - .raw_line(r#"enum StyleChildrenIteratorVoid { }"#) - .raw_line(r#"pub struct StyleChildrenIterator(StyleChildrenIteratorVoid);"#) - .raw_line(r#"pub type ServoElementSnapshotOwned = ::gecko_bindings::sugar::ownership::Owned;"#) - .raw_line(r#"pub type ServoElementSnapshotOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull;"#) - .raw_line(r#"pub type ServoElementSnapshotBorrowed<'a> = &'a ServoElementSnapshot;"#) - .raw_line(r#"pub type ServoElementSnapshotBorrowedOrNull<'a> = Option<&'a ServoElementSnapshot>;"#) - .raw_line(r#"pub type ServoElementSnapshotBorrowedMut<'a> = &'a mut ServoElementSnapshot;"#) - .raw_line(r#"pub type ServoElementSnapshotBorrowedMutOrNull<'a> = Option<&'a mut ServoElementSnapshot>;"#) - .raw_line(r#"pub type RawGeckoNodeBorrowed<'a> = &'a RawGeckoNode;"#) - .raw_line(r#"pub type RawGeckoNodeBorrowedOrNull<'a> = Option<&'a RawGeckoNode>;"#) - .raw_line(r#"pub type RawGeckoElementBorrowed<'a> = &'a RawGeckoElement;"#) - .raw_line(r#"pub type RawGeckoElementBorrowedOrNull<'a> = Option<&'a RawGeckoElement>;"#) - .raw_line(r#"pub type RawGeckoDocumentBorrowed<'a> = &'a RawGeckoDocument;"#) - .raw_line(r#"pub type RawGeckoDocumentBorrowedOrNull<'a> = Option<&'a RawGeckoDocument>;"#) - .raw_line(r#"pub type RawServoDeclarationBlockStrongBorrowed<'a> = &'a RawServoDeclarationBlockStrong;"#) - .raw_line(r#"pub type RawServoDeclarationBlockStrongBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlockStrong>;"#) - .raw_line(r#"pub type RawGeckoPresContextBorrowed<'a> = &'a RawGeckoPresContext;"#) - .raw_line(r#"pub type RawGeckoPresContextBorrowedOrNull<'a> = Option<&'a RawGeckoPresContext>;"#) - .raw_line(r#"pub type RawGeckoStyleAnimationListBorrowed<'a> = &'a RawGeckoStyleAnimationList;"#) - .raw_line(r#"pub type RawGeckoStyleAnimationListBorrowedOrNull<'a> = Option<&'a RawGeckoStyleAnimationList>;"#) - .raw_line(r#"pub type nsCSSValueBorrowed<'a> = &'a nsCSSValue;"#) - .raw_line(r#"pub type nsCSSValueBorrowedOrNull<'a> = Option<&'a nsCSSValue>;"#) - .raw_line(r#"pub type nsCSSValueBorrowedMut<'a> = &'a mut nsCSSValue;"#) - .raw_line(r#"pub type nsCSSValueBorrowedMutOrNull<'a> = Option<&'a mut nsCSSValue>;"#) - .raw_line(r#"pub type nsTimingFunctionBorrowed<'a> = &'a nsTimingFunction;"#) - .raw_line(r#"pub type nsTimingFunctionBorrowedOrNull<'a> = Option<&'a nsTimingFunction>;"#) - .raw_line(r#"pub type nsTimingFunctionBorrowedMut<'a> = &'a mut nsTimingFunction;"#) - .raw_line(r#"pub type nsTimingFunctionBorrowedMutOrNull<'a> = Option<&'a mut nsTimingFunction>;"#) - .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowed<'a> = &'a RawGeckoAnimationPropertySegment;"#) - .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationPropertySegment>;"#) - .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedMut<'a> = &'a mut RawGeckoAnimationPropertySegment;"#) - .raw_line(r#"pub type RawGeckoAnimationPropertySegmentBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationPropertySegment>;"#) - .raw_line(r#"pub type RawGeckoAnimationValueListBorrowed<'a> = &'a RawGeckoAnimationValueList;"#) - .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationValueList>;"#) - .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedMut<'a> = &'a mut RawGeckoAnimationValueList;"#) - .raw_line(r#"pub type RawGeckoAnimationValueListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationValueList>;"#) - .raw_line(r#"pub type RawGeckoComputedTimingBorrowed<'a> = &'a RawGeckoComputedTiming;"#) - .raw_line(r#"pub type RawGeckoComputedTimingBorrowedOrNull<'a> = Option<&'a RawGeckoComputedTiming>;"#) - .raw_line(r#"pub type RawGeckoComputedTimingBorrowedMut<'a> = &'a mut RawGeckoComputedTiming;"#) - .raw_line(r#"pub type RawGeckoComputedTimingBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoComputedTiming>;"#) - .raw_line(r#"pub type RawGeckoKeyframeListBorrowed<'a> = &'a RawGeckoKeyframeList;"#) - .raw_line(r#"pub type RawGeckoKeyframeListBorrowedOrNull<'a> = Option<&'a RawGeckoKeyframeList>;"#) - .raw_line(r#"pub type RawGeckoKeyframeListBorrowedMut<'a> = &'a mut RawGeckoKeyframeList;"#) - .raw_line(r#"pub type RawGeckoKeyframeListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoKeyframeList>;"#) - .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowed<'a> = &'a RawGeckoComputedKeyframeValuesList;"#) - .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedOrNull<'a> = Option<&'a RawGeckoComputedKeyframeValuesList>;"#) - .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedMut<'a> = &'a mut RawGeckoComputedKeyframeValuesList;"#) - .raw_line(r#"pub type RawGeckoComputedKeyframeValuesListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoComputedKeyframeValuesList>;"#) - .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowed<'a> = &'a RawGeckoFontFaceRuleList;"#) - .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedOrNull<'a> = Option<&'a RawGeckoFontFaceRuleList>;"#) - .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedMut<'a> = &'a mut RawGeckoFontFaceRuleList;"#) - .raw_line(r#"pub type RawGeckoFontFaceRuleListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoFontFaceRuleList>;"#) - .clang_arg("-x") - .clang_arg("c++") - .clang_arg("-std=c++14") - .clang_arg("-DTRACING=1") - .clang_arg("-DIMPL_LIBXUL") - .clang_arg("-DMOZ_STYLO_BINDINGS=1") - .clang_arg("-DMOZILLA_INTERNAL_API") - .clang_arg("-DRUST_BINDGEN") - .clang_arg("-DMOZ_STYLO") - .clang_arg("-DOS_POSIX=1") - .clang_arg("-DOS_LINUX=1") - .generate() - .expect("Should generate stylo bindings"); - - let now = Instant::now(); - - println!(""); - println!(""); - println!( - "Generated Stylo bindings in: {:?}", - now.duration_since(then) - ); - println!(""); - println!(""); - - // panic!("Uncomment this line to get timing logs"); -} diff --git a/tests/tests.rs b/tests/tests.rs deleted file mode 100644 index fd53f068ca..0000000000 --- a/tests/tests.rs +++ /dev/null @@ -1,421 +0,0 @@ -extern crate clap; -extern crate diff; -extern crate bindgen; -extern crate shlex; - -use bindgen::{Builder, builder, clang_version}; -use std::fs; -use std::io::{self, BufRead, BufReader, Error, ErrorKind, Read, Write}; -use std::path::PathBuf; -use std::process; -use std::sync::{Once, ONCE_INIT}; - -#[path = "../src/options.rs"] -mod options; -use options::builder_from_flags; - -// Run `rustfmt` on the given source string and return a tuple of the formatted -// bindings, and rustfmt's stderr. -fn rustfmt(source: String) -> (String, String) { - static CHECK_RUSTFMT: Once = ONCE_INIT; - - CHECK_RUSTFMT.call_once(|| { - let have_working_rustfmt = process::Command::new("rustup") - .args(&["run", "nightly", "rustfmt", "--version"]) - .stdout(process::Stdio::null()) - .stderr(process::Stdio::null()) - .status() - .ok() - .map_or(false, |status| status.success()); - - if !have_working_rustfmt { - panic!(" -The latest `rustfmt` is required to run the `bindgen` test suite. Install -`rustfmt` with: - - $ rustup update nightly - $ rustup run nightly cargo install -f rustfmt-nightly -"); - } - }); - - let mut child = process::Command::new("rustup") - .args(&[ - "run", - "nightly", - "rustfmt", - "--config-path", - concat!(env!("CARGO_MANIFEST_DIR"), "/tests/rustfmt.toml") - ]) - .stdin(process::Stdio::piped()) - .stdout(process::Stdio::piped()) - .stderr(process::Stdio::piped()) - .spawn() - .expect("should spawn `rustup run nightly rustfmt`"); - - let mut stdin = child.stdin.take().unwrap(); - let mut stdout = child.stdout.take().unwrap(); - let mut stderr = child.stderr.take().unwrap(); - - // Write to stdin in a new thread, so that we can read from stdout on this - // thread. This keeps the child from blocking on writing to its stdout which - // might block us from writing to its stdin. - let stdin_handle = ::std::thread::spawn(move || { - stdin.write_all(source.as_bytes()) - }); - - // Read stderr on a new thread for similar reasons. - let stderr_handle = ::std::thread::spawn(move || { - let mut output = vec![]; - io::copy(&mut stderr, &mut output) - .map(|_| String::from_utf8_lossy(&output).to_string()) - }); - - let mut output = vec![]; - io::copy(&mut stdout, &mut output) - .expect("Should copy stdout into vec OK"); - - // Ignore actual rustfmt status because it is often non-zero for trivial - // things. - let _ = child.wait().expect("should wait on rustfmt child OK"); - - stdin_handle.join() - .expect("writer thread should not have panicked") - .expect("should have written to child rustfmt's stdin OK"); - - let bindings = String::from_utf8(output) - .expect("rustfmt should only emit valid utf-8"); - - let stderr = stderr_handle.join() - .expect("stderr reader thread should not have panicked") - .expect("should have read child rustfmt's stderr OK"); - - (bindings, stderr) -} - -fn compare_generated_header( - header: &PathBuf, - builder: Builder, -) -> Result<(), Error> { - let file_name = header.file_name().ok_or(Error::new( - ErrorKind::Other, - "compare_generated_header expects a file", - ))?; - - let mut expectation = PathBuf::from(header); - expectation.pop(); - expectation.pop(); - expectation.push("expectations"); - expectation.push("tests"); - expectation.push(file_name); - expectation.set_extension("rs"); - - // If the expectation file doesn't exist, see if we have different test - // expectations for different libclang versions. - if !expectation.is_file() { - let file_name = expectation.file_name().unwrap().to_owned(); - expectation.pop(); - - if cfg!(feature = "testing_only_libclang_4") { - expectation.push("libclang-4"); - } else if cfg!(feature = "testing_only_libclang_5") { - expectation.push("libclang-5"); - } else if cfg!(feature = "testing_only_libclang_3_9") { - expectation.push("libclang-3.9"); - } else if cfg!(feature = "testing_only_libclang_3_8") { - expectation.push("libclang-3.8"); - } else { - match clang_version().parsed { - None => {} - Some(version) => { - let (maj, min) = version; - let version_str = if maj >= 5 { - "5".to_owned() - } else if maj == 4 { - "4".to_owned() - } else { - format!("{}.{}", maj, min) - }; - expectation.push(format!("libclang-{}", version_str)); - } - } - } - - expectation.push(file_name); - - if !expectation.is_file() { - panic!( - "missing test expectation file and/or 'testing_only_libclang_$VERSION' \ - feature for header '{}'; looking for expectation file at '{}'", - header.display(), - expectation.display() - ); - } - } - - // We skip the generate() error here so we get a full diff below - let (actual, rustfmt_stderr) = match builder.generate() { - Ok(bindings) => { - let actual = bindings.to_string(); - rustfmt(actual) - } - Err(()) => ("".to_string(), "".to_string()), - }; - println!("{}", rustfmt_stderr); - - let mut expected = String::new(); - { - if let Ok(expectation_file) = fs::File::open(&expectation) { - BufReader::new(expectation_file).read_to_string(&mut expected)?; - } - } - - let (expected, rustfmt_stderr) = rustfmt(expected); - println!("{}", rustfmt_stderr); - - if actual == expected { - if !actual.is_empty() { - return Ok(()); - } - return Err(Error::new( - ErrorKind::Other, - "Something's gone really wrong!", - )); - } - - println!("{}", rustfmt_stderr); - - println!("diff expected generated"); - println!("--- expected: {:?}", expectation); - println!("+++ generated from: {:?}", header); - - for diff in diff::lines(&expected, &actual) { - match diff { - diff::Result::Left(l) => println!("-{}", l), - diff::Result::Both(l, _) => println!(" {}", l), - diff::Result::Right(r) => println!("+{}", r), - } - } - - // Override the diff. - { - let mut expectation_file = fs::File::create(&expectation)?; - expectation_file.write_all(actual.as_bytes())?; - } - - Err(Error::new(ErrorKind::Other, "Header and binding differ!")) -} - -fn create_bindgen_builder(header: &PathBuf) -> Result, Error> { - let source = fs::File::open(header)?; - let reader = BufReader::new(source); - - // Scoop up bindgen-flags from test header - let mut flags = Vec::with_capacity(2); - - for line in reader.lines() { - let line = line?; - if !line.starts_with("// bindgen") { - continue; - } - - if line.contains("bindgen-flags: ") { - let extra_flags = line.split("bindgen-flags: ") - .last() - .and_then(shlex::split) - .unwrap(); - flags.extend(extra_flags.into_iter()); - } else if line.contains("bindgen-osx-only") { - let prepend_flags = ["--raw-line", "#![cfg(target_os=\"macos\")]"]; - flags = prepend_flags - .into_iter() - .map(ToString::to_string) - .chain(flags) - .collect(); - } else if line.contains("bindgen-generate-bindings-on-linux-only") && - !cfg!(target_os = "linux") - { - return Ok(None); - } - } - - // Different platforms have various different conventions like struct padding, mangling, etc. - // We make the default target as x86_64-unknown-linux - if flags.iter().all(|flag| !flag.starts_with("--target=")) { - if !flags.iter().any(|flag| flag == "--") { - flags.push("--".into()); - } - flags.push("--target=x86_64-unknown-linux".into()); - } - - // Fool builder_from_flags() into believing it has real env::args_os... - // - add "bindgen" as executable name 0th element - // - add header filename as 1st element - // - prepend raw lines so they're in the right order for expected output - // - append the test header's bindgen flags - let header_str = header.to_str().ok_or(Error::new( - ErrorKind::Other, - "Invalid header file name", - ))?; - - let prepend = [ - "bindgen", - // We format in `compare_generated_header` ourselves to have a little - // more control. - "--no-rustfmt-bindings", - "--with-derive-default", - header_str, - "--raw-line", - "", - "--raw-line", - "#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]", - "--raw-line", - "", - ]; - - let args = prepend.into_iter().map(ToString::to_string).chain( - flags - .into_iter(), - ); - - builder_from_flags(args).map(|(builder, _, _)| Some(builder)) -} - -macro_rules! test_header { - ($function:ident, $header:expr) => ( - #[test] - fn $function() { - let header = PathBuf::from($header); - let result = create_bindgen_builder(&header) - .and_then(|builder| { - if let Some(builder) = builder { - compare_generated_header(&header, builder) - } else { - Ok(()) - } - }); - - if let Err(err) = result { - panic!("{}", err); - } - } - ) -} - -// This file is generated by build.rs -include!(concat!(env!("OUT_DIR"), "/tests.rs")); - -#[test] -fn test_header_contents() { - let actual = builder() - .header_contents("test.h", "int foo(const char* a);") - .clang_arg("--target=x86_64-unknown-linux") - .generate() - .unwrap() - .to_string(); - - let (actual, stderr) = rustfmt(actual); - println!("{}", stderr); - - let (expected, _) = rustfmt("/* automatically generated by rust-bindgen */ - -extern \"C\" { - pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -".to_string()); - - assert_eq!( - expected, - actual - ); -} - -#[test] -fn test_multiple_header_calls_in_builder() { - let actual = builder() - .header(concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/headers/func_ptr.h" - )) - .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/char.h")) - .clang_arg("--target=x86_64-unknown-linux") - .generate() - .unwrap() - .to_string(); - - let (actual, stderr) = rustfmt(actual); - println!("{}", stderr); - - let expected = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs" - )); - let (expected, _) = rustfmt(expected.to_string()); - - if actual != expected { - println!("Generated bindings differ from expected!"); - - for diff in diff::lines(&actual, &expected) { - match diff { - diff::Result::Left(l) => println!("-{}", l), - diff::Result::Both(l, _) => println!(" {}", l), - diff::Result::Right(r) => println!("+{}", r), - } - } - - panic!(); - } -} - -#[test] -// Doesn't support executing sh file on Windows. -// We may want to implement it in Rust so that we support all systems. -#[cfg(not(target_os = "windows"))] -fn no_system_header_includes() { - use std::process::Command; - assert!( - Command::new("./ci/no-includes.sh") - .current_dir(env!("CARGO_MANIFEST_DIR")) - .spawn() - .expect("should spawn ./ci/no-includes.sh OK") - .wait() - .expect("should wait for ./ci/no-includes OK") - .success() - ); -} - -#[test] -fn dump_preprocessed_input() { - let arg_keyword = - concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/arg_keyword.hpp"); - let empty_layout = concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/headers/cpp-empty-layout.hpp" - ); - - builder() - .header(arg_keyword) - .header(empty_layout) - .dump_preprocessed_input() - .expect("should dump preprocessed input"); - - fn slurp(p: &str) -> String { - let mut contents = String::new(); - let mut file = fs::File::open(p).unwrap(); - file.read_to_string(&mut contents).unwrap(); - contents - } - - let bindgen_ii = slurp("__bindgen.ii"); - let arg_keyword = slurp(arg_keyword); - let empty_layout = slurp(empty_layout); - - assert!( - bindgen_ii.find(&arg_keyword).is_some(), - "arg_keyword.hpp is in the preprocessed file" - ); - assert!( - bindgen_ii.find(&empty_layout).is_some(), - "cpp-empty-layout.hpp is in the preprocessed file" - ); -} diff --git a/triagebot.toml b/triagebot.toml new file mode 100644 index 0000000000..77eb2925a3 --- /dev/null +++ b/triagebot.toml @@ -0,0 +1,30 @@ +[relabel] +allow-unauthenticated = [ + "A-*", + "C-*", + "E-*", + "I-*", + "S-*", + "bug", + "dependencies", + "enhancement", + "good first issue", + "hacktoberfest", + "help wanted", + "invalid", + "meta", + "msvc", + "next-release", + "question", + "This Week In Servo (TWiS)", + "windows", +] + +[autolabel."A-C++"] +trigger_files = [ + "**/*.cpp", + "**/*.cc", + "**/*.hpp", +] + +[assign] \ No newline at end of file

( + path: P + ) -> Result + where P: AsRef<::std::ffi::OsStr> { + let library = #library_new?; + #from_library + } + + pub unsafe fn from_library( + library: L + ) -> Result + where L: Into<::libloading::Library> { + let __library = library.into(); + #( #constructor_inits )* + Ok(#lib_ident { + __library, + #( #init_fields ),* + }) + } + + #( #struct_implementation )* + } + } + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn push_func( + &mut self, + ident: &Ident, + symbol: &str, + abi: ClangAbi, + is_variadic: bool, + is_required: bool, + args: &[TokenStream], + args_identifiers: &[TokenStream], + ret: &TokenStream, + ret_ty: &TokenStream, + attributes: &[TokenStream], + ctx: &BindgenContext, + ) { + if !is_variadic { + assert_eq!(args.len(), args_identifiers.len()); + } + + let signature = quote! { unsafe extern #abi fn ( #( #args),* ) #ret }; + let member = if is_required { + signature + } else { + quote! { Result<#signature, ::libloading::Error> } + }; + + self.struct_members.push(quote! { + pub #ident: #member, + }); + + // N.B: If the signature was required, it won't be wrapped in a Result<...> + // and we can simply call it directly. + let fn_ = if is_required { + quote! { self.#ident } + } else { + quote! { self.#ident.as_ref().expect("Expected function, got error.") } + }; + let call_body = if ctx.options().wrap_unsafe_ops { + quote!(unsafe { (#fn_)(#( #args_identifiers ),*) }) + } else { + quote!((#fn_)(#( #args_identifiers ),*) ) + }; + + // We can't implement variadic functions from C easily, so we allow to + // access the function pointer so that the user can call it just fine. + if !is_variadic { + self.struct_implementation.push(quote! { + #(#attributes)* + pub unsafe fn #ident ( &self, #( #args ),* ) #ret_ty { + #call_body + } + }); + } + + // N.B: Unwrap the signature upon construction if it is required to be resolved. + let symbol_cstr = + codegen::helpers::ast_ty::cstr_expr(symbol.to_string()); + let library_get = if ctx.options().wrap_unsafe_ops { + quote!(unsafe { __library.get(#symbol_cstr) }) + } else { + quote!(__library.get(#symbol_cstr)) + }; + + self.constructor_inits.push(if is_required { + quote! { + let #ident = #library_get.map(|sym| *sym)?; + } + } else { + quote! { + let #ident = #library_get.map(|sym| *sym); + } + }); + + self.init_fields.push(quote! { + #ident + }); + } + + pub fn push_var( + &mut self, + ident: &Ident, + symbol: &str, + ty: &TokenStream, + is_required: bool, + wrap_unsafe_ops: bool, + ) { + let member = if is_required { + quote! { *mut #ty } + } else { + quote! { Result<*mut #ty, ::libloading::Error> } + }; + + self.struct_members.push(quote! { + pub #ident: #member, + }); + + let deref = if is_required { + quote! { self.#ident } + } else { + quote! { *self.#ident.as_ref().expect("Expected variable, got error.") } + }; + self.struct_implementation.push(quote! { + pub unsafe fn #ident (&self) -> *mut #ty { + #deref + } + }); + + let symbol_cstr = + codegen::helpers::ast_ty::cstr_expr(symbol.to_string()); + + let library_get = if wrap_unsafe_ops { + quote!(unsafe { __library.get::<*mut #ty>(#symbol_cstr) }) + } else { + quote!(__library.get::<*mut #ty>(#symbol_cstr)) + }; + + let qmark = if is_required { quote!(?) } else { quote!() }; + + let var_get = quote! { + let #ident = #library_get.map(|sym| *sym)#qmark; + }; + + self.constructor_inits.push(var_get); + + self.init_fields.push(quote! { + #ident + }); + } +} diff --git a/bindgen/codegen/error.rs b/bindgen/codegen/error.rs new file mode 100644 index 0000000000..b82ba2aef1 --- /dev/null +++ b/bindgen/codegen/error.rs @@ -0,0 +1,52 @@ +use std::error; +use std::fmt; + +/// Errors that can occur during code generation. +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) enum Error { + /// Tried to generate an opaque blob for a type that did not have a layout. + NoLayoutForOpaqueBlob, + + /// Tried to instantiate an opaque template definition, or a template + /// definition that is too difficult for us to understand (like a partial + /// template specialization). + InstantiationOfOpaqueType, + + /// Function ABI is not supported. + UnsupportedAbi(&'static str), + + /// The pointer type size does not match the target's pointer size. + InvalidPointerSize { + ty_name: String, + ty_size: usize, + ptr_size: usize, + }, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::NoLayoutForOpaqueBlob => { + "Tried to generate an opaque blob, but had no layout.".fmt(f) + } + Error::InstantiationOfOpaqueType => { + "Instantiation of opaque template type or partial template specialization." + .fmt(f) + } + Error::UnsupportedAbi(abi) => { + write!( + f, + "{abi} ABI is not supported by the configured Rust target." + ) + } + Error::InvalidPointerSize { ty_name, ty_size, ptr_size } => { + write!(f, "The {ty_name} pointer type has size {ty_size} but the current target's pointer size is {ptr_size}.") + } + } + } +} + +impl error::Error for Error {} + +/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`. +pub(crate) type Result = ::std::result::Result; diff --git a/bindgen/codegen/helpers.rs b/bindgen/codegen/helpers.rs new file mode 100644 index 0000000000..9b86ba47b0 --- /dev/null +++ b/bindgen/codegen/helpers.rs @@ -0,0 +1,358 @@ +//! Helpers for code generation that don't need macro expansion. + +use proc_macro2::{Ident, Span}; + +use crate::ir::context::BindgenContext; +use crate::ir::layout::Layout; +use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; + +pub(crate) mod attributes { + use proc_macro2::{Ident, Span, TokenStream}; + use std::{borrow::Cow, str::FromStr}; + + pub(crate) fn repr(which: &str) -> TokenStream { + let which = Ident::new(which, Span::call_site()); + quote! { + #[repr( #which )] + } + } + + pub(crate) fn repr_list(which_ones: &[&str]) -> TokenStream { + let which_ones = which_ones + .iter() + .map(|one| TokenStream::from_str(one).expect("repr to be valid")); + quote! { + #[repr( #( #which_ones ),* )] + } + } + + pub(crate) fn derives(which_ones: &[&str]) -> TokenStream { + let which_ones = which_ones + .iter() + .map(|one| TokenStream::from_str(one).expect("derive to be valid")); + quote! { + #[derive( #( #which_ones ),* )] + } + } + + pub(crate) fn inline() -> TokenStream { + quote! { + #[inline] + } + } + + pub(crate) fn must_use() -> TokenStream { + quote! { + #[must_use] + } + } + + pub(crate) fn non_exhaustive() -> TokenStream { + quote! { + #[non_exhaustive] + } + } + + pub(crate) fn doc(comment: &str) -> TokenStream { + if comment.is_empty() { + quote!() + } else { + quote!(#[doc = #comment]) + } + } + + pub(crate) fn link_name(name: &str) -> TokenStream { + // LLVM mangles the name by default but it's already mangled. + // Prefixing the name with \u{1} should tell LLVM to not mangle it. + let name: Cow<'_, str> = if MANGLE { + name.into() + } else { + format!("\u{1}{name}").into() + }; + + quote! { + #[link_name = #name] + } + } +} + +/// The `ffi_safe` argument should be true if this is a type that the user might +/// reasonably use, e.g. not struct padding, where the `__BindgenOpaqueArray` is +/// just noise. +/// TODO: Should this be `MaybeUninit`, since padding bytes are effectively +/// uninitialized? +pub(crate) fn blob( + ctx: &BindgenContext, + layout: Layout, + ffi_safe: bool, +) -> syn::Type { + let align = layout.align.max(1); + // For alignments <= 4, it holds that the integer type of the same size aligns to that same + // size. For bigger alignments that's not guaranteed, e.g. on x86 u64 is aligned to 4 bytes. + if align <= 4 { + let ty = Layout::known_type_for_size(align).unwrap(); + let len = layout.size / align; + return if len == 1 { + ty + } else if !ffi_safe && len <= RUST_DERIVE_IN_ARRAY_LIMIT { + syn::parse_quote! { [#ty; #len] } + } else { + ctx.generated_opaque_array(1); + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__BindgenOpaqueArray<[#ty; #len]> } + } else { + syn::parse_quote! { __BindgenOpaqueArray<[#ty; #len]> } + } + }; + } + + ctx.generated_opaque_array(align); + let ident = format_ident!("__BindgenOpaqueArray{align}"); + let size = layout.size; + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::#ident<[u8; #size]> } + } else { + syn::parse_quote! { #ident<[u8; #size]> } + } +} + +/// Integer type of the same size as the given `Layout`. +pub(crate) fn integer_type(layout: Layout) -> Option { + Layout::known_type_for_size(layout.size) +} + +pub(crate) const BITFIELD_UNIT: &str = "__BindgenBitfieldUnit"; + +/// Generates a bitfield allocation unit type for a type with the given `Layout`. +pub(crate) fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> syn::Type { + let size = layout.size; + let bitfield_unit_name = Ident::new(BITFIELD_UNIT, Span::call_site()); + let ty = syn::parse_quote! { #bitfield_unit_name<[u8; #size]> }; + + if ctx.options().enable_cxx_namespaces { + return syn::parse_quote! { root::#ty }; + } + + ty +} + +pub(crate) mod ast_ty { + use crate::ir::context::BindgenContext; + use crate::ir::function::FunctionSig; + use crate::ir::layout::Layout; + use crate::ir::ty::{FloatKind, IntKind}; + use proc_macro2::TokenStream; + use std::str::FromStr; + + pub(crate) fn c_void(ctx: &BindgenContext) -> syn::Type { + // ctypes_prefix takes precedence + match ctx.options().ctypes_prefix { + Some(ref prefix) => { + let prefix = TokenStream::from_str(prefix.as_str()).unwrap(); + syn::parse_quote! { #prefix::c_void } + } + None => { + if ctx.options().use_core { + syn::parse_quote! { ::core::ffi::c_void } + } else { + syn::parse_quote! { ::std::os::raw::c_void } + } + } + } + } + + pub(crate) fn raw_type(ctx: &BindgenContext, name: &str) -> syn::Type { + let ident = ctx.rust_ident_raw(name); + match ctx.options().ctypes_prefix { + Some(ref prefix) => { + let prefix = TokenStream::from_str(prefix.as_str()).unwrap(); + syn::parse_quote! { #prefix::#ident } + } + None => { + if ctx.options().use_core && + ctx.options().rust_features().core_ffi_c + { + syn::parse_quote! { ::core::ffi::#ident } + } else { + syn::parse_quote! { ::std::os::raw::#ident } + } + } + } + } + + pub(crate) fn int_kind_rust_type( + ctx: &BindgenContext, + ik: IntKind, + layout: Option, + ) -> syn::Type { + match ik { + IntKind::Bool => syn::parse_quote! { bool }, + IntKind::Char { .. } => raw_type(ctx, "c_char"), + // The following is used only when an unusual command-line + // argument is used. bindgen_cchar16_t is not a real type; + // but this allows downstream postprocessors to distinguish + // this case and do something special for C++ bindings + // containing the C++ type char16_t. + IntKind::Char16 => syn::parse_quote! { bindgen_cchar16_t }, + IntKind::SChar => raw_type(ctx, "c_schar"), + IntKind::UChar => raw_type(ctx, "c_uchar"), + IntKind::Short => raw_type(ctx, "c_short"), + IntKind::UShort => raw_type(ctx, "c_ushort"), + IntKind::Int => raw_type(ctx, "c_int"), + IntKind::UInt => raw_type(ctx, "c_uint"), + IntKind::Long => raw_type(ctx, "c_long"), + IntKind::ULong => raw_type(ctx, "c_ulong"), + IntKind::LongLong => raw_type(ctx, "c_longlong"), + IntKind::ULongLong => raw_type(ctx, "c_ulonglong"), + IntKind::WChar => { + let layout = + layout.expect("Couldn't compute wchar_t's layout?"); + Layout::known_type_for_size(layout.size) + .expect("Non-representable wchar_t?") + } + + IntKind::I8 => syn::parse_quote! { i8 }, + IntKind::U8 => syn::parse_quote! { u8 }, + IntKind::I16 => syn::parse_quote! { i16 }, + IntKind::U16 => syn::parse_quote! { u16 }, + IntKind::I32 => syn::parse_quote! { i32 }, + IntKind::U32 => syn::parse_quote! { u32 }, + IntKind::I64 => syn::parse_quote! { i64 }, + IntKind::U64 => syn::parse_quote! { u64 }, + IntKind::Custom { name, .. } => { + syn::parse_str(name).expect("Invalid integer type.") + } + IntKind::U128 => { + if true { + syn::parse_quote! { u128 } + } else { + // Best effort thing, but wrong alignment + // unfortunately. + syn::parse_quote! { [u64; 2] } + } + } + IntKind::I128 => { + if true { + syn::parse_quote! { i128 } + } else { + syn::parse_quote! { [u64; 2] } + } + } + } + } + + pub(crate) fn float_kind_rust_type( + ctx: &BindgenContext, + fk: FloatKind, + layout: Option, + ) -> syn::Type { + // TODO: we probably should take the type layout into account more + // often? + // + // Also, maybe this one shouldn't be the default? + match (fk, ctx.options().convert_floats) { + (FloatKind::Float16, _) => { + // TODO: do f16 when rust lands it + ctx.generated_bindgen_float16(); + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__BindgenFloat16 } + } else { + syn::parse_quote! { __BindgenFloat16 } + } + } + (FloatKind::Float, true) => syn::parse_quote! { f32 }, + (FloatKind::Double, true) => syn::parse_quote! { f64 }, + (FloatKind::Float, false) => raw_type(ctx, "c_float"), + (FloatKind::Double, false) => raw_type(ctx, "c_double"), + (FloatKind::LongDouble, _) => { + if let Some(layout) = layout { + match layout.size { + 4 => syn::parse_quote! { f32 }, + 8 => syn::parse_quote! { f64 }, + // TODO(emilio): If rust ever gains f128 we should + // use it here and below. + _ => super::integer_type(layout) + .unwrap_or(syn::parse_quote! { f64 }), + } + } else { + debug_assert!( + false, + "How didn't we know the layout for a primitive type?" + ); + syn::parse_quote! { f64 } + } + } + (FloatKind::Float128, _) => { + if true { + syn::parse_quote! { u128 } + } else { + syn::parse_quote! { [u64; 2] } + } + } + } + } + + pub(crate) fn int_expr(val: i64) -> TokenStream { + // Don't use quote! { #val } because that adds the type suffix. + let val = proc_macro2::Literal::i64_unsuffixed(val); + quote!(#val) + } + + pub(crate) fn uint_expr(val: u64) -> TokenStream { + // Don't use quote! { #val } because that adds the type suffix. + let val = proc_macro2::Literal::u64_unsuffixed(val); + quote!(#val) + } + + pub(crate) fn cstr_expr(mut string: String) -> TokenStream { + string.push('\0'); + let b = proc_macro2::Literal::byte_string(string.as_bytes()); + quote! { + #b + } + } + + pub(crate) fn float_expr(f: f64) -> Result { + if f.is_finite() { + let val = proc_macro2::Literal::f64_unsuffixed(f); + + return Ok(quote!(#val)); + } + + if f.is_nan() { + return Ok(quote! { f64::NAN as _ }); + } + + if f.is_infinite() { + let tokens = if f.is_sign_positive() { + quote! { f64::INFINITY as _ } + } else { + quote! { f64::NEG_INFINITY as _ } + }; + return Ok(tokens); + } + + warn!("Unknown non-finite float number: {f:?}"); + Err(()) + } + + pub(crate) fn arguments_from_signature( + signature: &FunctionSig, + ctx: &BindgenContext, + ) -> Vec { + let mut unnamed_arguments = 0; + signature + .argument_types() + .iter() + .map(|&(ref name, _ty)| { + let name = if let Some(ref name) = *name { + ctx.rust_ident(name) + } else { + unnamed_arguments += 1; + ctx.rust_ident(format!("arg{unnamed_arguments}")) + }; + quote! { #name } + }) + .collect() + } +} diff --git a/bindgen/codegen/impl_debug.rs b/bindgen/codegen/impl_debug.rs new file mode 100644 index 0000000000..45394724de --- /dev/null +++ b/bindgen/codegen/impl_debug.rs @@ -0,0 +1,220 @@ +use crate::ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods}; +use crate::ir::context::BindgenContext; +use crate::ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName}; +use crate::ir::ty::TypeKind; +use std::fmt::Write as _; + +pub(crate) fn gen_debug_impl( + ctx: &BindgenContext, + fields: &[Field], + item: &Item, + kind: CompKind, +) -> proc_macro2::TokenStream { + let struct_name = item.canonical_name(ctx); + let mut format_string = format!("{struct_name} {{{{ "); + let mut tokens = vec![]; + + if item.is_opaque(ctx, &()) { + format_string.push_str("opaque"); + } else { + match kind { + CompKind::Union => { + format_string.push_str("union"); + } + CompKind::Struct => { + let processed_fields = fields.iter().filter_map(|f| match f { + Field::DataMember(ref fd) => fd.impl_debug(ctx, ()), + Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()), + }); + + for (i, (fstring, toks)) in processed_fields.enumerate() { + if i > 0 { + format_string.push_str(", "); + } + tokens.extend(toks); + format_string.push_str(&fstring); + } + } + } + } + + format_string.push_str(" }}"); + tokens.insert(0, quote! { #format_string }); + + let prefix = ctx.trait_prefix(); + + quote! { + fn fmt(&self, f: &mut ::#prefix::fmt::Formatter<'_>) -> ::#prefix ::fmt::Result { + write!(f, #( #tokens ),*) + } + } +} + +/// A trait for the things which we can codegen tokens that contribute towards a +/// generated `impl Debug`. +pub(crate) trait ImplDebug<'a> { + /// Any extra parameter required by this a particular `ImplDebug` implementation. + type Extra; + + /// Generate a format string snippet to be included in the larger `impl Debug` + /// format string, and the code to get the format string's interpolation values. + fn impl_debug( + &self, + ctx: &BindgenContext, + extra: Self::Extra, + ) -> Option<(String, Vec)>; +} + +impl ImplDebug<'_> for FieldData { + type Extra = (); + + fn impl_debug( + &self, + ctx: &BindgenContext, + _: Self::Extra, + ) -> Option<(String, Vec)> { + if let Some(name) = self.name() { + ctx.resolve_item(self.ty()).impl_debug(ctx, name) + } else { + None + } + } +} + +impl ImplDebug<'_> for BitfieldUnit { + type Extra = (); + + fn impl_debug( + &self, + ctx: &BindgenContext, + _: Self::Extra, + ) -> Option<(String, Vec)> { + let mut format_string = String::new(); + let mut tokens = vec![]; + for (i, bitfield) in self.bitfields().iter().enumerate() { + if i > 0 { + format_string.push_str(", "); + } + + if let Some(bitfield_name) = bitfield.name() { + let _ = write!(format_string, "{bitfield_name} : {{:?}}"); + let getter_name = bitfield.getter_name(); + let name_ident = ctx.rust_ident_raw(getter_name); + tokens.push(quote! { + self.#name_ident () + }); + } + } + + Some((format_string, tokens)) + } +} + +impl<'a> ImplDebug<'a> for Item { + type Extra = &'a str; + + fn impl_debug( + &self, + ctx: &BindgenContext, + name: &str, + ) -> Option<(String, Vec)> { + let name_ident = ctx.rust_ident(name); + + // We don't know if blocklisted items `impl Debug` or not, so we can't + // add them to the format string we're building up. + if !ctx.allowlisted_items().contains(&self.id()) { + return None; + } + + let ty = self.as_type()?; + + fn debug_print( + name: &str, + name_ident: &proc_macro2::TokenStream, + ) -> Option<(String, Vec)> { + Some(( + format!("{name}: {{:?}}"), + vec![quote! { + self.#name_ident + }], + )) + } + + match *ty.kind() { + // Handle the simple cases. + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::Comp(..) | + TypeKind::ObjCSel => debug_print(name, "e! { #name_ident }), + + TypeKind::TemplateInstantiation(ref inst) => { + if inst.is_opaque(ctx, self) { + Some((format!("{name}: opaque"), vec![])) + } else { + debug_print(name, "e! { #name_ident }) + } + } + + // The generic is not required to implement Debug, so we can not debug print that type + TypeKind::TypeParam => { + Some((format!("{name}: Non-debuggable generic"), vec![])) + } + + TypeKind::Array(_, len) => { + // Generics are not required to implement Debug + if self.has_type_param_in_array(ctx) { + Some((format!("{name}: Array with length {len}"), vec![])) + } else { + // The simple case + debug_print(name, "e! { #name_ident }) + } + } + TypeKind::Vector(_, len) => { + if ctx.options().use_core { + // There is no format! in core; reducing field visibility to avoid breaking + // no_std setups. + Some((format!("{name}(...)"), vec![])) + } else { + let self_ids = 0..len; + Some(( + format!("{name}({{}})"), + vec![quote! { + #(format!("{:?}", self.#self_ids)),* + }], + )) + } + } + + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::BlockPointer(t) => { + // We follow the aliases + ctx.resolve_item(t).impl_debug(ctx, name) + } + + TypeKind::Pointer(inner) => { + let inner_type = ctx.resolve_type(inner).canonical_type(ctx); + match *inner_type.kind() { + TypeKind::Function(ref sig) + if !sig.function_pointers_can_derive() => + { + Some((format!("{name}: FunctionPointer"), vec![])) + } + _ => debug_print(name, "e! { #name_ident }), + } + } + + TypeKind::Opaque => None, + } + } +} diff --git a/bindgen/codegen/impl_partialeq.rs b/bindgen/codegen/impl_partialeq.rs new file mode 100644 index 0000000000..a8edb4773d --- /dev/null +++ b/bindgen/codegen/impl_partialeq.rs @@ -0,0 +1,114 @@ +use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods}; +use crate::ir::context::BindgenContext; +use crate::ir::item::{IsOpaque, Item}; +use crate::ir::ty::TypeKind; + +/// Generate a manual implementation of `PartialEq` trait for the +/// specified compound type. +pub(crate) fn gen_partialeq_impl( + ctx: &BindgenContext, + comp_info: &CompInfo, + item: &Item, + ty_for_impl: &proc_macro2::TokenStream, +) -> Option { + let mut tokens = vec![]; + + if item.is_opaque(ctx, &()) { + tokens.push(quote! { + &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..] + }); + } else if comp_info.kind() == CompKind::Union { + assert!(!ctx.options().untagged_union); + tokens.push(quote! { + &self.bindgen_union_field[..] == &other.bindgen_union_field[..] + }); + } else { + for base in comp_info.base_members() { + if !base.requires_storage(ctx) { + continue; + } + + let ty_item = ctx.resolve_item(base.ty); + let field_name = &base.field_name; + tokens.push(gen_field(ctx, ty_item, field_name)); + } + + for field in comp_info.fields() { + match *field { + Field::DataMember(ref fd) => { + let ty_item = ctx.resolve_item(fd.ty()); + let name = fd.name().unwrap(); + tokens.push(gen_field(ctx, ty_item, name)); + } + Field::Bitfields(ref bu) => { + for bitfield in bu.bitfields() { + if bitfield.name().is_some() { + let getter_name = bitfield.getter_name(); + let name_ident = ctx.rust_ident_raw(getter_name); + tokens.push(quote! { + self.#name_ident () == other.#name_ident () + }); + } + } + } + } + } + } + + Some(quote! { + fn eq(&self, other: & #ty_for_impl) -> bool { + #( #tokens )&&* + } + }) +} + +fn gen_field( + ctx: &BindgenContext, + ty_item: &Item, + name: &str, +) -> proc_macro2::TokenStream { + fn quote_equals( + name_ident: &proc_macro2::Ident, + ) -> proc_macro2::TokenStream { + quote! { self.#name_ident == other.#name_ident } + } + + let name_ident = ctx.rust_ident(name); + let ty = ty_item.expect_type(); + + match *ty.kind() { + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Complex(..) | + TypeKind::Float(..) | + TypeKind::Enum(..) | + TypeKind::TypeParam | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::Reference(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::Comp(..) | + TypeKind::Pointer(_) | + TypeKind::Function(..) | + TypeKind::Array(..) | + TypeKind::TemplateInstantiation(..) | + TypeKind::Opaque => quote_equals(&name_ident), + TypeKind::Vector(_, len) => { + let self_ids = 0..len; + let other_ids = 0..len; + quote! { + #(self.#self_ids == other.#other_ids &&)* true + } + } + + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::BlockPointer(t) => { + let inner_item = ctx.resolve_item(t); + gen_field(ctx, inner_item, name) + } + } +} diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs new file mode 100644 index 0000000000..eee4f46121 --- /dev/null +++ b/bindgen/codegen/mod.rs @@ -0,0 +1,5959 @@ +mod dyngen; +pub(crate) mod error; + +mod helpers; +mod impl_debug; +mod impl_partialeq; +mod postprocessing; +mod serialize; +pub(crate) mod struct_layout; + +#[cfg(test)] +#[allow(warnings)] +pub(crate) mod bitfield_unit; +#[cfg(all(test, target_endian = "little"))] +mod bitfield_unit_tests; + +use self::dyngen::DynamicItems; +use self::helpers::attributes; +use self::struct_layout::StructLayoutTracker; + +use super::BindgenOptions; + +use crate::callbacks::{ + AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId, FieldInfo, + TypeKind as DeriveTypeKind, +}; +use crate::codegen::error::Error; +use crate::ir::analysis::{HasVtable, Sizedness}; +use crate::ir::annotations::{ + Annotations, FieldAccessorKind, FieldVisibilityKind, +}; +use crate::ir::comp::{ + Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods, + Method, MethodKind, +}; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::derive::{ + CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq, + CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd, +}; +use crate::ir::dot; +use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; +use crate::ir::function::{ + ClangAbi, Function, FunctionKind, FunctionSig, Linkage, +}; +use crate::ir::int::IntKind; +use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath}; +use crate::ir::item_kind::ItemKind; +use crate::ir::layout::Layout; +use crate::ir::module::Module; +use crate::ir::objc::{ObjCInterface, ObjCMethod}; +use crate::ir::template::{ + AsTemplateParam, TemplateInstantiation, TemplateParameters, +}; +use crate::ir::ty::{Type, TypeKind}; +use crate::ir::var::Var; + +use proc_macro2::{Ident, Span}; +use quote::{ToTokens, TokenStreamExt}; + +use crate::{Entry, HashMap, HashSet}; +use std::borrow::Cow; +use std::cell::Cell; +use std::collections::VecDeque; +use std::ffi::CStr; +use std::fmt::{self, Write}; +use std::ops; +use std::str::{self, FromStr}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum CodegenError { + Serialize { msg: String, loc: String }, + Io(String), +} + +impl From for CodegenError { + fn from(err: std::io::Error) -> Self { + Self::Io(err.to_string()) + } +} + +impl fmt::Display for CodegenError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Serialize { msg, loc } => { + write!(f, "serialization error at {loc}: {msg}") + } + Self::Io(err) => err.fmt(f), + } + } +} + +// Name of type defined in constified enum module +pub(crate) static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type"; + +fn top_level_path( + ctx: &BindgenContext, + item: &Item, +) -> Vec { + let mut path = vec![quote! { self }]; + + if ctx.options().enable_cxx_namespaces { + for _ in 0..item.codegen_depth(ctx) { + path.push(quote! { super }); + } + } + + path +} + +fn root_import( + ctx: &BindgenContext, + module: &Item, +) -> proc_macro2::TokenStream { + assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up"); + assert!(module.is_module()); + + let mut path = top_level_path(ctx, module); + + let root = ctx.root_module().canonical_name(ctx); + let root_ident = ctx.rust_ident(root); + path.push(quote! { #root_ident }); + + let mut tokens = quote! {}; + tokens.append_separated(path, quote!(::)); + + quote! { + #[allow(unused_imports)] + use #tokens ; + } +} + +bitflags! { + #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + struct DerivableTraits: u16 { + const DEBUG = 1 << 0; + const DEFAULT = 1 << 1; + const COPY = 1 << 2; + const CLONE = 1 << 3; + const HASH = 1 << 4; + const PARTIAL_ORD = 1 << 5; + const ORD = 1 << 6; + const PARTIAL_EQ = 1 << 7; + const EQ = 1 << 8; + } +} + +fn derives_of_item( + item: &Item, + ctx: &BindgenContext, + packed: bool, +) -> DerivableTraits { + let mut derivable_traits = DerivableTraits::empty(); + + if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { + derivable_traits |= DerivableTraits::COPY; + + // FIXME: This requires extra logic if you have a big array in a + // templated struct. The reason for this is that the magic: + // fn clone(&self) -> Self { *self } + // doesn't work for templates. + // + // It's not hard to fix though. + derivable_traits |= DerivableTraits::CLONE; + } else if packed { + // If the struct or union is packed, deriving from Copy is required for + // deriving from any other trait. + return derivable_traits; + } + + if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() { + derivable_traits |= DerivableTraits::DEBUG; + } + + if item.can_derive_default(ctx) && !item.annotations().disallow_default() { + derivable_traits |= DerivableTraits::DEFAULT; + } + + if item.can_derive_hash(ctx) { + derivable_traits |= DerivableTraits::HASH; + } + + if item.can_derive_partialord(ctx) { + derivable_traits |= DerivableTraits::PARTIAL_ORD; + } + + if item.can_derive_ord(ctx) { + derivable_traits |= DerivableTraits::ORD; + } + + if item.can_derive_partialeq(ctx) { + derivable_traits |= DerivableTraits::PARTIAL_EQ; + } + + if item.can_derive_eq(ctx) { + derivable_traits |= DerivableTraits::EQ; + } + + derivable_traits +} + +impl From for Vec<&'static str> { + fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> { + [ + (DerivableTraits::DEBUG, "Debug"), + (DerivableTraits::DEFAULT, "Default"), + (DerivableTraits::COPY, "Copy"), + (DerivableTraits::CLONE, "Clone"), + (DerivableTraits::HASH, "Hash"), + (DerivableTraits::PARTIAL_ORD, "PartialOrd"), + (DerivableTraits::ORD, "Ord"), + (DerivableTraits::PARTIAL_EQ, "PartialEq"), + (DerivableTraits::EQ, "Eq"), + ] + .iter() + .filter_map(|&(flag, derive)| { + Some(derive).filter(|_| derivable_traits.contains(flag)) + }) + .collect() + } +} + +struct WrapAsVariadic { + new_name: String, + idx_of_va_list_arg: usize, +} + +struct CodegenResult<'a> { + items: Vec, + dynamic_items: DynamicItems, + + /// A monotonic counter used to add stable unique ID's to stuff that doesn't + /// need to be referenced by anything. + codegen_id: &'a Cell, + + /// Whether a bindgen union has been generated at least once. + saw_bindgen_union: bool, + + /// Whether an incomplete array has been generated at least once. + saw_incomplete_array: bool, + + /// Whether Objective C types have been seen at least once. + saw_objc: bool, + + /// Whether Apple block types have been seen at least once. + saw_block: bool, + + /// Whether a bitfield allocation unit has been seen at least once. + saw_bitfield_unit: bool, + + items_seen: HashSet, + /// The set of generated function/var names, needed because in C/C++ is + /// legal to do something like: + /// + /// ```c++ + /// extern "C" { + /// void foo(); + /// extern int bar; + /// } + /// + /// extern "C" { + /// void foo(); + /// extern int bar; + /// } + /// ``` + /// + /// Being these two different declarations. + functions_seen: HashSet, + vars_seen: HashSet, + + /// Used for making bindings to overloaded functions. Maps from a canonical + /// function name to the number of overloads we have already codegen'd for + /// that name. This lets us give each overload a unique suffix. + overload_counters: HashMap, + + /// List of items to serialize. With optionally the argument for the wrap as + /// variadic transformation to be applied. + items_to_serialize: Vec<(ItemId, Option)>, +} + +impl<'a> CodegenResult<'a> { + fn new(codegen_id: &'a Cell) -> Self { + CodegenResult { + items: vec![], + dynamic_items: DynamicItems::new(), + saw_bindgen_union: false, + saw_incomplete_array: false, + saw_objc: false, + saw_block: false, + saw_bitfield_unit: false, + codegen_id, + items_seen: Default::default(), + functions_seen: Default::default(), + vars_seen: Default::default(), + overload_counters: Default::default(), + items_to_serialize: Default::default(), + } + } + + fn dynamic_items(&mut self) -> &mut DynamicItems { + &mut self.dynamic_items + } + + fn saw_bindgen_union(&mut self) { + self.saw_bindgen_union = true; + } + + fn saw_incomplete_array(&mut self) { + self.saw_incomplete_array = true; + } + + fn saw_objc(&mut self) { + self.saw_objc = true; + } + + fn saw_block(&mut self) { + self.saw_block = true; + } + + fn saw_bitfield_unit(&mut self) { + self.saw_bitfield_unit = true; + } + + fn seen>(&self, item: Id) -> bool { + self.items_seen.contains(&item.into()) + } + + fn set_seen>(&mut self, item: Id) { + self.items_seen.insert(item.into()); + } + + fn seen_function(&self, name: &str) -> bool { + self.functions_seen.contains(name) + } + + fn saw_function(&mut self, name: &str) { + self.functions_seen.insert(name.into()); + } + + /// Get the overload number for the given function name. Increments the + /// counter internally so the next time we ask for the overload for this + /// name, we get the incremented value, and so on. + fn overload_number(&mut self, name: &str) -> u32 { + let counter = self.overload_counters.entry(name.into()).or_insert(0); + let number = *counter; + *counter += 1; + number + } + + fn seen_var(&self, name: &str) -> bool { + self.vars_seen.contains(name) + } + + fn saw_var(&mut self, name: &str) { + self.vars_seen.insert(name.into()); + } + + fn inner(&mut self, cb: F) -> Vec + where + F: FnOnce(&mut Self), + { + let mut new = Self::new(self.codegen_id); + + cb(&mut new); + + self.saw_incomplete_array |= new.saw_incomplete_array; + self.saw_objc |= new.saw_objc; + self.saw_block |= new.saw_block; + self.saw_bitfield_unit |= new.saw_bitfield_unit; + self.saw_bindgen_union |= new.saw_bindgen_union; + + new.items + } +} + +impl ops::Deref for CodegenResult<'_> { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.items + } +} + +impl ops::DerefMut for CodegenResult<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.items + } +} + +/// A trait to convert a rust type into a pointer, optionally const, to the same +/// type. +trait ToPtr { + fn to_ptr(self, is_const: bool) -> syn::Type; +} + +impl ToPtr for syn::Type { + fn to_ptr(self, is_const: bool) -> syn::Type { + if is_const { + syn::parse_quote! { *const #self } + } else { + syn::parse_quote! { *mut #self } + } + } +} + +/// An extension trait for `syn::Type` that lets us append any implicit +/// template parameters that exist for some type, if necessary. +trait WithImplicitTemplateParams { + fn with_implicit_template_params( + self, + ctx: &BindgenContext, + item: &Item, + ) -> Self; +} + +impl WithImplicitTemplateParams for syn::Type { + fn with_implicit_template_params( + self, + ctx: &BindgenContext, + item: &Item, + ) -> Self { + let item = item.id().into_resolver().through_type_refs().resolve(ctx); + + let params = match *item.expect_type().kind() { + TypeKind::UnresolvedTypeRef(..) => { + unreachable!("already resolved unresolved type refs") + } + TypeKind::ResolvedTypeRef(..) => { + unreachable!("we resolved item through type refs") + } + // None of these types ever have implicit template parameters. + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Pointer(..) | + TypeKind::Reference(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Array(..) | + TypeKind::TypeParam | + TypeKind::Opaque | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::TemplateInstantiation(..) => None, + _ => { + let params = item.used_template_params(ctx); + if params.is_empty() { + None + } else { + Some(params.into_iter().map(|p| { + p.try_to_rust_ty(ctx, &()).expect( + "template params cannot fail to be a rust type", + ) + })) + } + } + }; + + if let Some(params) = params { + syn::parse_quote! { #self<#(#params),*> } + } else { + self + } + } +} + +trait CodeGenerator { + /// Extra information from the caller. + type Extra; + + /// Extra information returned to the caller. + type Return; + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + extra: &Self::Extra, + ) -> Self::Return; +} + +impl Item { + fn process_before_codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult, + ) -> bool { + if !self.is_enabled_for_codegen(ctx) { + return false; + } + + if self.is_blocklisted(ctx) || result.seen(self.id()) { + debug!( + "::process_before_codegen: Ignoring hidden or seen: \ + self = {self:?}" + ); + return false; + } + + if !ctx.codegen_items().contains(&self.id()) { + // TODO(emilio, #453): Figure out what to do when this happens + // legitimately, we could track the opaque stuff and disable the + // assertion there I guess. + warn!("Found non-allowlisted item in code generation: {self:?}"); + } + + result.set_seen(self.id()); + true + } +} + +impl CodeGenerator for Item { + type Extra = (); + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + _extra: &(), + ) { + debug!("::codegen: self = {self:?}"); + if !self.process_before_codegen(ctx, result) { + return; + } + + match *self.kind() { + ItemKind::Module(ref module) => { + module.codegen(ctx, result, self); + } + ItemKind::Function(ref fun) => { + fun.codegen(ctx, result, self); + } + ItemKind::Var(ref var) => { + var.codegen(ctx, result, self); + } + ItemKind::Type(ref ty) => { + ty.codegen(ctx, result, self); + } + } + } +} + +impl CodeGenerator for Module { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug!("::codegen: item = {item:?}"); + + let codegen_self = |result: &mut CodegenResult, + found_any: &mut bool| { + for child in self.children() { + if ctx.codegen_items().contains(child) { + *found_any = true; + ctx.resolve_item(*child).codegen(ctx, result, &()); + } + } + + if item.id() == ctx.root_module() { + if result.saw_block { + utils::prepend_block_header(ctx, &mut *result); + } + if result.saw_bindgen_union { + utils::prepend_union_types(ctx, &mut *result); + } + if result.saw_incomplete_array { + utils::prepend_incomplete_array_types(ctx, &mut *result); + } + if ctx.need_bindgen_float16_type() { + utils::prepend_float16_type(&mut *result); + } + if ctx.need_bindgen_complex_type() { + utils::prepend_complex_type(&mut *result); + } + utils::prepend_opaque_array_types(ctx, &mut *result); + if result.saw_objc { + utils::prepend_objc_header(ctx, &mut *result); + } + if result.saw_bitfield_unit { + utils::prepend_bitfield_unit_type(ctx, &mut *result); + } + } + }; + + if !ctx.options().enable_cxx_namespaces || + (self.is_inline() && + !ctx.options().conservative_inline_namespaces) + { + codegen_self(result, &mut false); + return; + } + + let mut found_any = false; + let inner_items = result.inner(|result| { + result.push(root_import(ctx, item)); + + let path = item + .namespace_aware_canonical_path(ctx) + .join("::") + .into_boxed_str(); + if let Some(raw_lines) = ctx.options().module_lines.get(&path) { + for raw_line in raw_lines { + found_any = true; + result.push( + proc_macro2::TokenStream::from_str(raw_line).unwrap(), + ); + } + } + + codegen_self(result, &mut found_any); + }); + + // Don't bother creating an empty module. + if !found_any { + return; + } + + let name = item.canonical_name(ctx); + let ident = ctx.rust_ident(name); + result.push(if item.id() == ctx.root_module() { + quote! { + #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] + pub mod #ident { + #( #inner_items )* + } + } + } else { + quote! { + pub mod #ident { + #( #inner_items )* + } + } + }); + } +} + +impl CodeGenerator for Var { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + use crate::ir::var::VarType; + debug!("::codegen: item = {item:?}"); + debug_assert!(item.is_enabled_for_codegen(ctx)); + + let canonical_name = item.canonical_name(ctx); + + if result.seen_var(&canonical_name) { + return; + } + result.saw_var(&canonical_name); + + let canonical_ident = ctx.rust_ident(&canonical_name); + + // We can't generate bindings to static variables of templates. The + // number of actual variables for a single declaration are open ended + // and we don't know what instantiations do or don't exist. + if !item.all_template_params(ctx).is_empty() { + return; + } + + let mut attrs = vec![]; + if let Some(comment) = item.comment(ctx) { + attrs.push(attributes::doc(&comment)); + } + + let var_ty = self.ty(); + let ty = var_ty.to_rust_ty_or_opaque(ctx, &()); + + if let Some(val) = self.val() { + let const_expr = match *val { + VarType::Bool(val) => Some(val.to_token_stream()), + VarType::Int(val) => { + let int_kind = var_ty + .into_resolver() + .through_type_aliases() + .through_type_refs() + .resolve(ctx) + .expect_type() + .as_integer() + .unwrap(); + let val = if int_kind.is_signed() { + helpers::ast_ty::int_expr(val) + } else { + helpers::ast_ty::uint_expr(val as _) + }; + Some(val) + } + VarType::String(ref bytes) => { + let prefix = ctx.trait_prefix(); + + let options = ctx.options(); + let rust_features = options.rust_features; + + let mut cstr_bytes = bytes.clone(); + cstr_bytes.push(0); + let len = proc_macro2::Literal::usize_unsuffixed( + cstr_bytes.len(), + ); + let cstr = + if options.generate_cstr && rust_features.const_cstr { + CStr::from_bytes_with_nul(&cstr_bytes).ok() + } else { + None + }; + if let Some(cstr) = cstr { + let cstr_ty = quote! { ::#prefix::ffi::CStr }; + if rust_features.literal_cstr { + let cstr = proc_macro2::Literal::c_string(cstr); + result.push(quote! { + #(#attrs)* + pub const #canonical_ident: &#cstr_ty = #cstr; + }); + } else { + let bytes = + proc_macro2::Literal::byte_string(&cstr_bytes); + result.push(quote! { + #(#attrs)* + #[allow(unsafe_code)] + pub const #canonical_ident: &#cstr_ty = unsafe { + #cstr_ty::from_bytes_with_nul_unchecked(#bytes) + }; + }); + } + } else { + // TODO: Here we ignore the type we just made up, probably + // we should refactor how the variable type and ty ID work. + let array_ty = quote! { [u8; #len] }; + let bytes = + proc_macro2::Literal::byte_string(&cstr_bytes); + let lifetime = + if true { None } else { Some(quote! { 'static }) } + .into_iter(); + + result.push(quote! { + #(#attrs)* + pub const #canonical_ident: &#(#lifetime )*#array_ty = #bytes ; + }); + } + None + } + VarType::Float(f) => helpers::ast_ty::float_expr(f).ok(), + VarType::Char(c) => Some(c.to_token_stream()), + }; + + if let Some(mut val) = const_expr { + let var_ty_item = ctx.resolve_item(var_ty); + if matches!( + var_ty_item.alias_style(ctx), + AliasVariation::NewType | AliasVariation::NewTypeDeref + ) { + val = quote! { #ty(#val) }; + } + result.push(quote! { + #(#attrs)* + pub const #canonical_ident : #ty = #val ; + }); + } + } else { + let symbol: &str = self.link_name().unwrap_or_else(|| { + let link_name = + self.mangled_name().unwrap_or_else(|| self.name()); + if utils::names_will_be_identical_after_mangling( + &canonical_name, + link_name, + None, + ) { + canonical_name.as_str() + } else { + attrs.push(attributes::link_name::(link_name)); + link_name + } + }); + + let maybe_mut = if self.is_const() { + quote! {} + } else { + quote! { mut } + }; + + let safety = ctx + .options() + .rust_features + .unsafe_extern_blocks + .then(|| quote!(unsafe)); + + let tokens = quote!( + #safety extern "C" { + #(#attrs)* + pub static #maybe_mut #canonical_ident: #ty; + } + ); + + if ctx.options().dynamic_library_name.is_some() { + result.dynamic_items().push_var( + &canonical_ident, + symbol, + &self + .ty() + .to_rust_ty_or_opaque(ctx, &()) + .into_token_stream(), + ctx.options().dynamic_link_require_all, + ctx.options().wrap_unsafe_ops, + ); + } else { + result.push(tokens); + } + } + } +} + +impl CodeGenerator for Type { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug!("::codegen: item = {item:?}"); + debug_assert!(item.is_enabled_for_codegen(ctx)); + + match *self.kind() { + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Array(..) | + TypeKind::Vector(..) | + TypeKind::Pointer(..) | + TypeKind::Reference(..) | + TypeKind::Function(..) | + TypeKind::ResolvedTypeRef(..) | + TypeKind::Opaque | + TypeKind::TypeParam => { + // These items don't need code generation, they only need to be + // converted to rust types in fields, arguments, and such. + // NOTE(emilio): If you add to this list, make sure to also add + // it to BindgenContext::compute_allowlisted_and_codegen_items. + } + TypeKind::TemplateInstantiation(ref inst) => { + inst.codegen(ctx, result, item); + } + TypeKind::BlockPointer(inner) => { + if !ctx.options().generate_block { + return; + } + + let inner_item = + inner.into_resolver().through_type_refs().resolve(ctx); + let name = item.canonical_name(ctx); + + let inner_rust_type = { + if let TypeKind::Function(fnsig) = + inner_item.kind().expect_type().kind() + { + utils::fnsig_block(ctx, fnsig) + } else { + panic!("invalid block typedef: {inner_item:?}") + } + }; + + let rust_name = ctx.rust_ident(name); + + let mut tokens = if let Some(comment) = item.comment(ctx) { + attributes::doc(&comment) + } else { + quote! {} + }; + + tokens.append_all(quote! { + pub type #rust_name = #inner_rust_type ; + }); + + result.push(tokens); + result.saw_block(); + } + TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), + TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => { + let inner_item = + inner.into_resolver().through_type_refs().resolve(ctx); + let name = item.canonical_name(ctx); + let path = item.canonical_path(ctx); + + { + let through_type_aliases = inner + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(ctx); + + // Try to catch the common pattern: + // + // typedef struct foo { ... } foo; + // + // here, and also other more complex cases like #946. + if through_type_aliases.canonical_path(ctx) == path { + return; + } + } + + // If this is a known named type, disallow generating anything + // for it too. If size_t -> usize conversions are enabled, we + // need to check that these conversions are permissible, but + // nothing needs to be generated, still. + let spelling = self.name().expect("Unnamed alias?"); + if utils::type_from_named(ctx, spelling).is_some() { + if let "size_t" | "ssize_t" = spelling { + let layout = inner_item + .kind() + .expect_type() + .layout(ctx) + .expect("No layout?"); + assert_eq!( + layout.size, + ctx.target_pointer_size(), + "Target platform requires `--no-size_t-is-usize`. The size of `{spelling}` ({}) does not match the target pointer size ({})", + layout.size, + ctx.target_pointer_size(), + ); + assert_eq!( + layout.align, + ctx.target_pointer_size(), + "Target platform requires `--no-size_t-is-usize`. The alignment of `{spelling}` ({}) does not match the target pointer size ({})", + layout.align, + ctx.target_pointer_size(), + ); + } + return; + } + + let mut outer_params = item.used_template_params(ctx); + + let is_opaque = item.is_opaque(ctx, &()); + let inner_rust_type = if is_opaque { + outer_params = vec![]; + self.to_opaque(ctx, item) + } else { + // Its possible that we have better layout information than + // the inner type does, so fall back to an opaque blob based + // on our layout if converting the inner item fails. + inner_item + .try_to_rust_ty_or_opaque(ctx, &()) + .unwrap_or_else(|_| self.to_opaque(ctx, item)) + .with_implicit_template_params(ctx, inner_item) + }; + + { + // FIXME(emilio): This is a workaround to avoid generating + // incorrect type aliases because of types that we haven't + // been able to resolve (because, eg, they depend on a + // template parameter). + // + // It's kind of a shame not generating them even when they + // could be referenced, but we already do the same for items + // with invalid template parameters, and at least this way + // they can be replaced, instead of generating plain invalid + // code. + let inner_canon_type = + inner_item.expect_type().canonical_type(ctx); + if inner_canon_type.is_invalid_type_param() { + warn!( + "Item contained invalid named type, skipping: \ + {item:?}, {inner_item:?}" + ); + return; + } + } + + let rust_name = ctx.rust_ident(&name); + + utils::call_discovered_item_callback(ctx, item, || { + DiscoveredItem::Alias { + alias_name: rust_name.to_string(), + alias_for: DiscoveredItemId::new( + inner_item.id().as_usize(), + ), + } + }); + + let mut tokens = if let Some(comment) = item.comment(ctx) { + attributes::doc(&comment) + } else { + quote! {} + }; + + let alias_style = item.alias_style(ctx); + + // We prefer using `pub use` over `pub type` because of: + // https://github.com/rust-lang/rust/issues/26264 + if matches!(inner_rust_type, syn::Type::Path(_)) && + outer_params.is_empty() && + !is_opaque && + alias_style == AliasVariation::TypeAlias && + inner_item.expect_type().canonical_type(ctx).is_enum() + { + tokens.append_all(quote! { + pub use + }); + let path = top_level_path(ctx, item); + tokens.append_separated(path, quote!(::)); + tokens.append_all(quote! { + :: #inner_rust_type as #rust_name ; + }); + result.push(tokens); + return; + } + + tokens.append_all(match alias_style { + AliasVariation::TypeAlias => quote! { + pub type #rust_name + }, + AliasVariation::NewType | AliasVariation::NewTypeDeref => { + let mut attributes = + vec![attributes::repr("transparent")]; + let packed = false; // Types can't be packed in Rust. + let derivable_traits = + derives_of_item(item, ctx, packed); + let mut derives: Vec<_> = derivable_traits.into(); + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives = + ctx.options().all_callbacks(|cb| { + cb.add_derives(&DeriveInfo { + name: &name, + kind: DeriveTypeKind::Struct, + }) + }); + // In most cases this will be a no-op, since custom_derives will be empty. + derives + .extend(custom_derives.iter().map(|s| s.as_str())); + attributes.push(attributes::derives(&derives)); + + let custom_attributes = + ctx.options().all_callbacks(|cb| { + cb.add_attributes(&AttributeInfo { + name: &name, + kind: DeriveTypeKind::Struct, + }) + }); + attributes.extend( + custom_attributes + .iter() + .map(|s| s.parse().unwrap()), + ); + + quote! { + #( #attributes )* + pub struct #rust_name + } + } + }); + + let params: Vec<_> = outer_params + .into_iter() + .filter_map(|p| p.as_template_param(ctx, &())) + .collect(); + if params + .iter() + .any(|p| ctx.resolve_type(*p).is_invalid_type_param()) + { + warn!( + "Item contained invalid template \ + parameter: {item:?}" + ); + return; + } + let params: Vec<_> = params + .iter() + .map(|p| { + p.try_to_rust_ty(ctx, &()).expect( + "type parameters can always convert to rust ty OK", + ) + }) + .collect(); + + if !params.is_empty() { + tokens.append_all(quote! { + < #( #params ),* > + }); + } + + tokens.append_all(match alias_style { + AliasVariation::TypeAlias => quote! { + = #inner_rust_type ; + }, + AliasVariation::NewType | AliasVariation::NewTypeDeref => { + let visibility = ctx + .options() + .last_callback(|cb| { + cb.field_visibility(FieldInfo { + type_name: &item.canonical_name(ctx), + field_name: "0", + field_type_name: inner_item + .expect_type() + .name(), + }) + }) + .unwrap_or(ctx.options().default_visibility); + let access_spec = access_specifier(visibility); + quote! { + (#access_spec #inner_rust_type) ; + } + } + }); + + if alias_style == AliasVariation::NewTypeDeref { + let prefix = ctx.trait_prefix(); + tokens.append_all(quote! { + impl ::#prefix::ops::Deref for #rust_name { + type Target = #inner_rust_type; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl ::#prefix::ops::DerefMut for #rust_name { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + }); + } + + result.push(tokens); + } + TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), + TypeKind::ObjCId | TypeKind::ObjCSel => { + result.saw_objc(); + } + TypeKind::ObjCInterface(ref interface) => { + interface.codegen(ctx, result, item); + } + ref u @ TypeKind::UnresolvedTypeRef(..) => { + unreachable!("Should have been resolved after parsing {u:?}!") + } + } + } +} + +struct Vtable<'a> { + item_id: ItemId, + /// A reference to the originating compound object. + #[allow(dead_code)] + comp_info: &'a CompInfo, +} + +impl<'a> Vtable<'a> { + fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self { + Vtable { item_id, comp_info } + } +} + +impl CodeGenerator for Vtable<'_> { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + assert_eq!(item.id(), self.item_id); + debug_assert!(item.is_enabled_for_codegen(ctx)); + let name = ctx.rust_ident(self.canonical_name(ctx)); + + // For now, we will only generate vtables for classes that: + // - do not inherit from others (compilers merge VTable from primary parent class). + // - do not contain a virtual destructor (requires ordering; platforms generate different vtables). + if ctx.options().vtable_generation && + self.comp_info.base_members().is_empty() && + self.comp_info.destructor().is_none() + { + let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx)); + + let methods = self + .comp_info + .methods() + .iter() + .filter_map(|m| { + if !m.is_virtual() { + return None; + } + + let function_item = ctx.resolve_item(m.signature()); + let function = function_item.expect_function(); + let signature_item = ctx.resolve_item(function.signature()); + let TypeKind::Function(ref signature) = signature_item.expect_type().kind() else { panic!("Function signature type mismatch") }; + + // FIXME: Is there a canonical name without the class prepended? + let function_name = function_item.canonical_name(ctx); + + // FIXME: Need to account for overloading with times_seen (separately from regular function path). + let function_name = ctx.rust_ident(function_name); + let mut args = utils::fnsig_arguments(ctx, signature); + let ret = utils::fnsig_return_ty(ctx, signature); + + args[0] = if m.is_const() { + quote! { this: *const #class_ident } + } else { + quote! { this: *mut #class_ident } + }; + + Some(quote! { + pub #function_name : unsafe extern "C" fn( #( #args ),* ) #ret + }) + }) + .collect::>(); + + result.push(quote! { + #[repr(C)] + pub struct #name { + #( #methods ),* + } + }); + } else { + // For the cases we don't support, simply generate an empty struct. + let void = helpers::ast_ty::c_void(ctx); + + result.push(quote! { + #[repr(C)] + pub struct #name ( #void ); + }); + } + } +} + +impl ItemCanonicalName for Vtable<'_> { + fn canonical_name(&self, ctx: &BindgenContext) -> String { + format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx)) + } +} + +impl TryToRustTy for Vtable<'_> { + type Extra = (); + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { + let name = ctx.rust_ident(self.canonical_name(ctx)); + Ok(syn::parse_quote! { #name }) + } +} + +impl CodeGenerator for TemplateInstantiation { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug_assert!(item.is_enabled_for_codegen(ctx)); + + // Although uses of instantiations don't need code generation, and are + // just converted to rust types in fields, vars, etc, we take this + // opportunity to generate tests for their layout here. If the + // instantiation is opaque, then its presumably because we don't + // properly understand it (maybe because of specializations), and so we + // shouldn't emit layout tests either. + if !ctx.options().layout_tests || self.is_opaque(ctx, item) { + return; + } + + // For consistency with other layout tests, gate this on offset_of. + let compile_time = ctx.options().rust_features().offset_of; + + // If there are any unbound type parameters, then we can't generate a + // layout test because we aren't dealing with a concrete type with a + // concrete size and alignment. + if ctx.uses_any_template_parameters(item.id()) { + return; + } + + let layout = item.kind().expect_type().layout(ctx); + + if let Some(layout) = layout { + let size = layout.size; + let align = layout.align; + + let name = item.full_disambiguated_name(ctx); + let fn_name = if compile_time { + None + } else { + let mut fn_name = + format!("__bindgen_test_layout_{name}_instantiation"); + let times_seen = result.overload_number(&fn_name); + if times_seen > 0 { + write!(&mut fn_name, "_{times_seen}").unwrap(); + } + Some(ctx.rust_ident_raw(fn_name)) + }; + + let prefix = ctx.trait_prefix(); + let ident = item.to_rust_ty_or_opaque(ctx, &()); + let size_of_expr = quote! { + ::#prefix::mem::size_of::<#ident>() + }; + let align_of_expr = quote! { + ::#prefix::mem::align_of::<#ident>() + }; + let size_of_err = + format!("Size of template specialization: {name}"); + let align_of_err = + format!("Align of template specialization: {name}"); + + if compile_time { + // In an ideal world this would be assert_eq!, but that is not + // supported in const fn due to the need for string formatting. + // If #size_of_expr > #size, this will index OOB, and if + // #size_of_expr < #size, the subtraction will overflow, both + // of which print enough information to see what has gone wrong. + result.push(quote! { + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [#size_of_err][#size_of_expr - #size]; + [#align_of_err][#align_of_expr - #align]; + }; + }); + } else { + result.push(quote! { + #[test] + fn #fn_name() { + assert_eq!(#size_of_expr, #size, #size_of_err); + assert_eq!(#align_of_expr, #align, #align_of_err); + } + }); + } + } + } +} + +/// Trait for implementing the code generation of a struct or union field. +trait FieldCodegen<'a> { + type Extra; + + #[allow(clippy::too_many_arguments)] + fn codegen( + &self, + ctx: &BindgenContext, + visibility_kind: FieldVisibilityKind, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + parent_item: &Item, + last_field: bool, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + extra: Self::Extra, + ) where + F: Extend, + M: Extend; +} + +impl FieldCodegen<'_> for Field { + type Extra = (); + + fn codegen( + &self, + ctx: &BindgenContext, + visibility_kind: FieldVisibilityKind, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + parent_item: &Item, + last_field: bool, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, + { + match *self { + Field::DataMember(ref data) => { + data.codegen( + ctx, + visibility_kind, + accessor_kind, + parent, + parent_item, + last_field, + result, + struct_layout, + fields, + methods, + (), + ); + } + Field::Bitfields(ref unit) => { + unit.codegen( + ctx, + visibility_kind, + accessor_kind, + parent, + parent_item, + last_field, + result, + struct_layout, + fields, + methods, + (), + ); + } + } + } +} + +fn wrap_union_field_if_needed( + ctx: &BindgenContext, + struct_layout: &StructLayoutTracker, + ty: syn::Type, + result: &mut CodegenResult, +) -> syn::Type { + if struct_layout.is_rust_union() { + if struct_layout.can_copy_union_fields() { + ty + } else { + let prefix = ctx.trait_prefix(); + syn::parse_quote! { ::#prefix::mem::ManuallyDrop<#ty> } + } + } else { + result.saw_bindgen_union(); + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__BindgenUnionField<#ty> } + } else { + syn::parse_quote! { __BindgenUnionField<#ty> } + } + } +} + +impl FieldCodegen<'_> for FieldData { + type Extra = (); + + fn codegen( + &self, + ctx: &BindgenContext, + parent_visibility_kind: FieldVisibilityKind, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + parent_item: &Item, + last_field: bool, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, + { + // Bitfields are handled by `FieldCodegen` implementations for + // `BitfieldUnit` and `Bitfield`. + assert!(self.bitfield_width().is_none()); + + let field_item = + self.ty().into_resolver().through_type_refs().resolve(ctx); + let field_ty = field_item.expect_type(); + let ty = self + .ty() + .to_rust_ty_or_opaque(ctx, &()) + .with_implicit_template_params(ctx, field_item); + + // NB: If supported, we use proper `union` types. + let ty = if parent.is_union() { + wrap_union_field_if_needed(ctx, struct_layout, ty, result) + } else if let Some(item) = field_ty.is_incomplete_array(ctx) { + // Only FAM if its the last field + if ctx.options().flexarray_dst && last_field { + struct_layout.saw_flexible_array(); + syn::parse_quote! { FAM } + } else { + result.saw_incomplete_array(); + + let inner = item.to_rust_ty_or_opaque(ctx, &()); + + if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__IncompleteArrayField<#inner> } + } else { + syn::parse_quote! { __IncompleteArrayField<#inner> } + } + } + } else { + ty + }; + + let mut field = quote! {}; + if ctx.options().generate_comments { + if let Some(raw_comment) = self.comment() { + let comment = ctx.options().process_comment(raw_comment); + field = attributes::doc(&comment); + } + } + + let field_name = self + .name() + .map(|name| ctx.rust_mangle(name).into_owned()) + .expect("Each field should have a name in codegen!"); + let field_name = field_name.as_str(); + let field_ident = ctx.rust_ident_raw(field_name); + + if let Some(padding_field) = + struct_layout.saw_field(field_name, field_ty, self.offset()) + { + fields.extend(Some(padding_field)); + } + + let visibility = compute_visibility( + ctx, + self.is_public(), + ctx.options().last_callback(|cb| { + cb.field_visibility(FieldInfo { + type_name: &parent_item.canonical_name(ctx), + field_name, + field_type_name: field_ty.name(), + }) + }), + self.annotations(), + parent_visibility_kind, + ); + let accessor_kind = + self.annotations().accessor_kind().unwrap_or(accessor_kind); + + match visibility { + FieldVisibilityKind::Private => { + field.append_all(quote! { + #field_ident : #ty , + }); + } + FieldVisibilityKind::PublicCrate => { + field.append_all(quote! { + pub(crate) #field_ident : #ty , + }); + } + FieldVisibilityKind::Public => { + field.append_all(quote! { + pub #field_ident : #ty , + }); + } + } + + fields.extend(Some(field)); + + // TODO: Factor the following code out, please! + if accessor_kind == FieldAccessorKind::None { + return; + } + + let getter_name = ctx.rust_ident_raw(format!("get_{field_name}")); + let mutable_getter_name = + ctx.rust_ident_raw(format!("get_{field_name}_mut")); + + methods.extend(Some(match accessor_kind { + FieldAccessorKind::None => unreachable!(), + FieldAccessorKind::Regular => { + quote! { + #[inline] + pub fn #getter_name(&self) -> & #ty { + &self.#field_ident + } + + #[inline] + pub fn #mutable_getter_name(&mut self) -> &mut #ty { + &mut self.#field_ident + } + } + } + FieldAccessorKind::Unsafe => { + quote! { + #[inline] + pub unsafe fn #getter_name(&self) -> & #ty { + &self.#field_ident + } + + #[inline] + pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty { + &mut self.#field_ident + } + } + } + FieldAccessorKind::Immutable => { + quote! { + #[inline] + pub fn #getter_name(&self) -> & #ty { + &self.#field_ident + } + } + } + })); + } +} + +impl BitfieldUnit { + /// Get the constructor name for this bitfield unit. + fn ctor_name(&self) -> proc_macro2::TokenStream { + let ctor_name = Ident::new( + &format!("new_bitfield_{}", self.nth()), + Span::call_site(), + ); + quote! { + #ctor_name + } + } +} + +impl Bitfield { + /// Extend an under construction bitfield unit constructor with this + /// bitfield. This sets the relevant bits on the `__bindgen_bitfield_unit` + /// variable that's being constructed. + fn extend_ctor_impl( + &self, + ctx: &BindgenContext, + param_name: &proc_macro2::TokenStream, + mut ctor_impl: proc_macro2::TokenStream, + ) -> proc_macro2::TokenStream { + let bitfield_ty = ctx.resolve_type(self.ty()); + let bitfield_ty_layout = bitfield_ty + .layout(ctx) + .expect("Bitfield without layout? Gah!"); + let bitfield_int_ty = helpers::integer_type(bitfield_ty_layout).expect( + "Should already have verified that the bitfield is \ + representable as an int", + ); + + let offset = self.offset_into_unit(); + let width = self.width() as u8; + let prefix = ctx.trait_prefix(); + + ctor_impl.append_all(quote! { + __bindgen_bitfield_unit.set( + #offset, + #width, + { + let #param_name: #bitfield_int_ty = unsafe { + ::#prefix::mem::transmute(#param_name) + }; + #param_name as u64 + } + ); + }); + + ctor_impl + } +} + +fn access_specifier( + visibility: FieldVisibilityKind, +) -> proc_macro2::TokenStream { + match visibility { + FieldVisibilityKind::Private => quote! {}, + FieldVisibilityKind::PublicCrate => quote! { pub(crate) }, + FieldVisibilityKind::Public => quote! { pub }, + } +} + +/// Compute a fields or structs visibility based on multiple conditions. +/// 1. If the element was declared public, and we respect such CXX accesses specs +/// (context option) => By default Public, but this can be overruled by an `annotation`. +/// +/// 2. If the element was declared private, and we respect such CXX accesses specs +/// (context option) => By default Private, but this can be overruled by an `annotation`. +/// +/// 3. If we do not respect visibility modifiers, the result depends on the `annotation`, +/// if any, or the passed `default_kind`. +/// +fn compute_visibility( + ctx: &BindgenContext, + is_declared_public: bool, + callback_override: Option, + annotations: &Annotations, + default_kind: FieldVisibilityKind, +) -> FieldVisibilityKind { + callback_override + .or_else(|| annotations.visibility_kind()) + .unwrap_or_else(|| { + match (is_declared_public, ctx.options().respect_cxx_access_specs) { + (true, true) => { + // declared as public, cxx specs are respected + FieldVisibilityKind::Public + } + (false, true) => { + // declared as private, cxx specs are respected + FieldVisibilityKind::Private + } + (_, false) => { + // cxx specs are not respected, declaration does not matter. + default_kind + } + } + }) +} + +impl FieldCodegen<'_> for BitfieldUnit { + type Extra = (); + + fn codegen( + &self, + ctx: &BindgenContext, + visibility_kind: FieldVisibilityKind, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + parent_item: &Item, + last_field: bool, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, + { + use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; + + result.saw_bitfield_unit(); + + let layout = self.layout(); + let unit_field_ty = helpers::bitfield_unit(ctx, layout); + let field_ty = { + let unit_field_ty = unit_field_ty.clone(); + if parent.is_union() { + wrap_union_field_if_needed( + ctx, + struct_layout, + unit_field_ty, + result, + ) + } else { + unit_field_ty + } + }; + + let unit_field_name = format!("_bitfield_{}", self.nth()); + let unit_field_ident = ctx.rust_ident(&unit_field_name); + + let ctor_name = self.ctor_name(); + let mut ctor_params = vec![]; + let mut ctor_impl = quote! {}; + + // We cannot generate any constructor if the underlying storage can't + // implement AsRef<[u8]> / AsMut<[u8]> / etc, or can't derive Default. + // + // We don't check `larger_arrays` here because Default does still have + // the 32 items limitation. + let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT; + + let mut unit_visibility = visibility_kind; + let bfields = self.bitfields(); + for (idx, bf) in bfields.iter().enumerate() { + // Codegen not allowed for anonymous bitfields + if bf.name().is_none() { + continue; + } + + let mut bitfield_representable_as_int = true; + let mut bitfield_visibility = visibility_kind; + bf.codegen( + ctx, + visibility_kind, + accessor_kind, + parent, + parent_item, + last_field && idx == bfields.len() - 1, + result, + struct_layout, + fields, + methods, + ( + &unit_field_name, + &unit_field_ty, + &mut bitfield_representable_as_int, + &mut bitfield_visibility, + ), + ); + if bitfield_visibility < unit_visibility { + unit_visibility = bitfield_visibility; + } + + // Generating a constructor requires the bitfield to be representable as an integer. + if !bitfield_representable_as_int { + generate_ctor = false; + continue; + } + + let param_name = bitfield_getter_name(ctx, bf); + let bitfield_ty_item = ctx.resolve_item(bf.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); + let bitfield_ty = + bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); + + ctor_params.push(quote! { + #param_name : #bitfield_ty + }); + ctor_impl = bf.extend_ctor_impl(ctx, ¶m_name, ctor_impl); + } + + let access_spec = access_specifier(unit_visibility); + + let field = quote! { + #access_spec #unit_field_ident : #field_ty , + }; + fields.extend(Some(field)); + + if generate_ctor { + methods.extend(Some(quote! { + #[inline] + #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty { + let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default(); + #ctor_impl + __bindgen_bitfield_unit + } + })); + } + + struct_layout.saw_bitfield_unit(layout); + } +} + +fn bitfield_getter_name( + ctx: &BindgenContext, + bitfield: &Bitfield, +) -> proc_macro2::TokenStream { + let name = bitfield.getter_name(); + let name = ctx.rust_ident_raw(name); + quote! { #name } +} + +fn bitfield_raw_getter_name( + ctx: &BindgenContext, + bitfield: &Bitfield, +) -> proc_macro2::TokenStream { + let name = bitfield.getter_name(); + let name = ctx.rust_ident_raw(format!("{name}_raw")); + quote! { #name } +} + +fn bitfield_setter_name( + ctx: &BindgenContext, + bitfield: &Bitfield, +) -> proc_macro2::TokenStream { + let setter = bitfield.setter_name(); + let setter = ctx.rust_ident_raw(setter); + quote! { #setter } +} + +fn bitfield_raw_setter_name( + ctx: &BindgenContext, + bitfield: &Bitfield, +) -> proc_macro2::TokenStream { + let setter = bitfield.setter_name(); + let setter = ctx.rust_ident_raw(format!("{setter}_raw")); + quote! { #setter } +} + +impl<'a> FieldCodegen<'a> for Bitfield { + type Extra = ( + &'a str, + &'a syn::Type, + &'a mut bool, + &'a mut FieldVisibilityKind, + ); + + fn codegen( + &self, + ctx: &BindgenContext, + visibility_kind: FieldVisibilityKind, + _accessor_kind: FieldAccessorKind, + parent: &CompInfo, + parent_item: &Item, + _last_field: bool, + _result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + _fields: &mut F, + methods: &mut M, + ( + unit_field_name, + unit_field_ty, + bitfield_representable_as_int, + bitfield_visibility, + ): ( + &'a str, + &'a syn::Type, + &mut bool, + &'a mut FieldVisibilityKind, + ), + ) where + F: Extend, + M: Extend, + { + let prefix = ctx.trait_prefix(); + let getter_name = bitfield_getter_name(ctx, self); + let setter_name = bitfield_setter_name(ctx, self); + let raw_getter_name = bitfield_raw_getter_name(ctx, self); + let raw_setter_name = bitfield_raw_setter_name(ctx, self); + let unit_field_ident = Ident::new(unit_field_name, Span::call_site()); + + let bitfield_ty_item = ctx.resolve_item(self.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); + let bitfield_ty_ident = bitfield_ty.name(); + + let bitfield_ty_layout = bitfield_ty + .layout(ctx) + .expect("Bitfield without layout? Gah!"); + let bitfield_int_ty = + if let Some(int_ty) = helpers::integer_type(bitfield_ty_layout) { + *bitfield_representable_as_int = true; + int_ty + } else { + *bitfield_representable_as_int = false; + return; + }; + + let bitfield_ty = + bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); + + let offset = self.offset_into_unit(); + let width = self.width() as u8; + + let override_visibility = self.name().and_then(|field_name| { + ctx.options().last_callback(|cb| { + cb.field_visibility(FieldInfo { + type_name: &parent_item.canonical_name(ctx), + field_name, + field_type_name: bitfield_ty_ident, + }) + }) + }); + *bitfield_visibility = compute_visibility( + ctx, + self.is_public(), + override_visibility, + self.annotations(), + visibility_kind, + ); + let access_spec = access_specifier(*bitfield_visibility); + + if parent.is_union() && !struct_layout.is_rust_union() { + methods.extend(Some(quote! { + #[inline] + #access_spec fn #getter_name(&self) -> #bitfield_ty { + unsafe { + ::#prefix::mem::transmute( + self.#unit_field_ident.as_ref().get(#offset, #width) + as #bitfield_int_ty + ) + } + } + + #[inline] + #access_spec fn #setter_name(&mut self, val: #bitfield_ty) { + unsafe { + let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); + self.#unit_field_ident.as_mut().set( + #offset, + #width, + val as u64 + ) + } + } + })); + + methods.extend(Some(quote! { + #[inline] + #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty { + unsafe { + ::#prefix::mem::transmute(<#unit_field_ty>::raw_get( + (*::#prefix::ptr::addr_of!((*this).#unit_field_ident)).as_ref() as *const _, + #offset, + #width, + ) as #bitfield_int_ty) + } + } + + #[inline] + #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) { + unsafe { + let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); + <#unit_field_ty>::raw_set( + (*::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident)).as_mut() as *mut _, + #offset, + #width, + val as u64, + ) + } + } + })); + } else { + methods.extend(Some(quote! { + #[inline] + #access_spec fn #getter_name(&self) -> #bitfield_ty { + unsafe { + ::#prefix::mem::transmute( + self.#unit_field_ident.get(#offset, #width) + as #bitfield_int_ty + ) + } + } + + #[inline] + #access_spec fn #setter_name(&mut self, val: #bitfield_ty) { + unsafe { + let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); + self.#unit_field_ident.set( + #offset, + #width, + val as u64 + ) + } + } + })); + + methods.extend(Some(quote! { + #[inline] + #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty { + unsafe { + ::#prefix::mem::transmute(<#unit_field_ty>::raw_get( + ::#prefix::ptr::addr_of!((*this).#unit_field_ident), + #offset, + #width, + ) as #bitfield_int_ty) + } + } + + #[inline] + #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) { + unsafe { + let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); + <#unit_field_ty>::raw_set( + ::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident), + #offset, + #width, + val as u64, + ) + } + } + })); + } + } +} + +impl CodeGenerator for CompInfo { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug!("::codegen: item = {item:?}"); + debug_assert!(item.is_enabled_for_codegen(ctx)); + + // Don't output classes with template parameters that aren't types, and + // also don't output template specializations, neither total or partial. + if self.has_non_type_template_params() { + return; + } + + let ty = item.expect_type(); + let layout = ty.layout(ctx); + let mut packed = self.is_packed(ctx, layout.as_ref()); + + let canonical_name = item.canonical_name(ctx); + let canonical_ident = ctx.rust_ident(&canonical_name); + + // Generate the vtable from the method list if appropriate. + // + // TODO: I don't know how this could play with virtual methods that are + // not in the list of methods found by us, we'll see. Also, could the + // order of the vtable pointers vary? + // + // FIXME: Once we generate proper vtables, we need to codegen the + // vtable, but *not* generate a field for it in the case that + // HasVtable::has_vtable_ptr is false but HasVtable::has_vtable is true. + // + // Also, we need to generate the vtable in such a way it "inherits" from + // the parent too. + let is_opaque = item.is_opaque(ctx, &()); + let mut fields = vec![]; + let visibility = item + .annotations() + .visibility_kind() + .unwrap_or(ctx.options().default_visibility); + let mut struct_layout = StructLayoutTracker::new( + ctx, + self, + ty, + &canonical_name, + visibility, + packed, + ); + + let mut generic_param_names = vec![]; + + for (idx, ty) in item.used_template_params(ctx).iter().enumerate() { + let param = ctx.resolve_type(*ty); + let name = param.name().unwrap(); + let ident = ctx.rust_ident(name); + generic_param_names.push(ident.clone()); + + let prefix = ctx.trait_prefix(); + let field_name = ctx.rust_ident(format!("_phantom_{idx}")); + fields.push(quote! { + pub #field_name : ::#prefix::marker::PhantomData< + ::#prefix::cell::UnsafeCell<#ident> + > , + }); + } + + if !is_opaque { + if item.has_vtable_ptr(ctx) { + let vtable = Vtable::new(item.id(), self); + vtable.codegen(ctx, result, item); + + let vtable_type = vtable + .try_to_rust_ty(ctx, &()) + .expect("vtable to Rust type conversion is infallible") + .to_ptr(true); + + fields.push(quote! { + pub vtable_: #vtable_type , + }); + + struct_layout.saw_vtable(); + } + + for base in self.base_members() { + if !base.requires_storage(ctx) { + continue; + } + + let inner_item = ctx.resolve_item(base.ty); + let inner = inner_item + .to_rust_ty_or_opaque(ctx, &()) + .with_implicit_template_params(ctx, inner_item); + let field_name = ctx.rust_ident(&base.field_name); + + struct_layout.saw_base(inner_item.expect_type()); + + let visibility = match ( + base.is_public(), + ctx.options().respect_cxx_access_specs, + ) { + (true, true) => FieldVisibilityKind::Public, + (false, true) => FieldVisibilityKind::Private, + _ => ctx.options().default_visibility, + }; + + let access_spec = access_specifier(visibility); + fields.push(quote! { + #access_spec #field_name: #inner, + }); + } + } + + let mut methods = vec![]; + if !is_opaque { + let struct_accessor_kind = item + .annotations() + .accessor_kind() + .unwrap_or(FieldAccessorKind::None); + let field_decls = self.fields(); + for (idx, field) in field_decls.iter().enumerate() { + field.codegen( + ctx, + visibility, + struct_accessor_kind, + self, + item, + idx == field_decls.len() - 1, + result, + &mut struct_layout, + &mut fields, + &mut methods, + (), + ); + } + // Check whether an explicit padding field is needed + // at the end. + if let Some(comp_layout) = layout { + fields.extend( + struct_layout + .add_tail_padding(&canonical_name, comp_layout), + ); + } + } + + if is_opaque { + // Opaque item should not have generated methods, fields. + debug_assert!(fields.is_empty()); + debug_assert!(methods.is_empty()); + } + + let is_union = self.kind() == CompKind::Union; + let layout = item.kind().expect_type().layout(ctx); + let zero_sized = item.is_zero_sized(ctx); + let forward_decl = self.is_forward_declaration(); + + let mut explicit_align = None; + + // C++ requires every struct to be addressable, so what C++ compilers do + // is making the struct 1-byte sized. + // + // This is apparently not the case for C, see: + // https://github.com/rust-lang/rust-bindgen/issues/551 + // + // Just get the layout, and assume C++ if not. + // + // NOTE: This check is conveniently here to avoid the dummy fields we + // may add for unused template parameters. + if !forward_decl && zero_sized { + let has_address = if is_opaque { + // Generate the address field if it's an opaque type and + // couldn't determine the layout of the blob. + layout.is_none() + } else { + layout.map_or(true, |l| l.size != 0) + }; + + if has_address { + let layout = Layout::new(1, 1); + struct_layout.saw_field_with_layout( + "_address", + layout, + /* offset = */ Some(0), + ); + fields.push(quote! { + pub _address: u8, + }); + } + } + + if is_opaque { + match layout { + Some(l) => { + explicit_align = Some(l.align); + let ty = helpers::blob(ctx, l, false); + fields.push(quote! { + pub _bindgen_opaque_blob: #ty , + }); + } + None => { + if !forward_decl { + warn!("Opaque type without layout! Expect dragons!"); + } + } + } + } else if !is_union && !zero_sized { + if let Some(padding_field) = + layout.and_then(|layout| struct_layout.pad_struct(layout)) + { + fields.push(padding_field); + } + + if let Some(layout) = layout { + if struct_layout.requires_explicit_align(layout) { + if layout.align == 1 { + packed = true; + } else { + explicit_align = Some(layout.align); + } + } + } + } else if is_union && !forward_decl { + if let Some(layout) = layout { + // TODO(emilio): It'd be nice to unify this with the struct path above somehow. + if struct_layout.requires_explicit_align(layout) { + explicit_align = Some(layout.align); + } + if !struct_layout.is_rust_union() { + let ty = helpers::blob(ctx, layout, false); + fields.push(quote! { + pub bindgen_union_field: #ty, + }); + } + } + } + + if forward_decl { + fields.push(quote! { + _unused: [u8; 0], + }); + } + + let (flex_array_generic, flex_inner_ty) = if ctx.options().flexarray_dst + { + match self.flex_array_member(ctx) { + Some(ty) => { + let inner = ty.to_rust_ty_or_opaque(ctx, &()); + ( + Some(quote! { FAM: ?Sized = [ #inner; 0 ] }), + Some(quote! { #inner }), + ) + } + None => (None, None), + } + } else { + (None, None) + }; + + // Generics, including the flexible array member. + // + // generics - generic parameters for the struct declaration + // impl_generics_labels - generic parameters for `impl<...>` + // impl_generics_params - generic parameters for `impl structname<...>` + // + // `impl` blocks are for non-FAM related impls like Default, etc + let (generics, impl_generics_labels, impl_generics_params) = + if !generic_param_names.is_empty() || flex_array_generic.is_some() { + let (flex_sized, flex_fam) = match flex_inner_ty.as_ref() { + None => (None, None), + Some(ty) => ( + Some(quote! { [ #ty; 0 ] }), + Some(quote! { FAM: ?Sized = [ #ty; 0 ] }), + ), + }; + + ( + quote! { + < #( #generic_param_names , )* #flex_fam > + }, + quote! { + < #( #generic_param_names , )* > + }, + quote! { + < #( #generic_param_names , )* #flex_sized > + }, + ) + } else { + (quote! {}, quote! {}, quote! {}) + }; + + let mut attributes = vec![]; + let mut needs_clone_impl = false; + let mut needs_default_impl = false; + let mut needs_debug_impl = false; + let mut needs_partialeq_impl = false; + let needs_flexarray_impl = flex_array_generic.is_some(); + if let Some(comment) = item.comment(ctx) { + attributes.push(attributes::doc(&comment)); + } + + // if a type has both a "packed" attribute and an "align(N)" attribute, then check if the + // "packed" attr is redundant, and do not include it if so. + if packed && + !is_opaque && + !(explicit_align.is_some() && + self.already_packed(ctx).unwrap_or(false)) + { + let n = layout.map_or(1, |l| l.align); + let packed_repr = if n == 1 { + "packed".to_string() + } else { + format!("packed({n})") + }; + attributes.push(attributes::repr_list(&["C", &packed_repr])); + } else { + attributes.push(attributes::repr("C")); + } + + // Ensure that the struct has the correct alignment even in presence of alignas and co. + if let Some(explicit) = explicit_align { + // If we need explicit alignment and can do it, we prefer to insert a dummy field at + // the beginning of the struct. This avoids hitting + // https://github.com/rust-lang/rust-bindgen/issues/2179 + // Do it for bitfields only for now for backwards compat. + if self.has_bitfields() && explicit <= 8 { + let align_ty = match explicit { + 8 => quote! { u64 }, + 4 => quote! { u32 }, + 2 => quote! { u16 }, + _ => quote! { u8 }, + }; + let align_field = quote! { + pub _bindgen_align: [#align_ty; 0], + }; + fields.insert(0, align_field); + } else { + let explicit = helpers::ast_ty::int_expr(explicit as i64); + attributes.push(quote! { + #[repr(align(#explicit))] + }); + } + } + + let derivable_traits = derives_of_item(item, ctx, packed); + if !derivable_traits.contains(DerivableTraits::DEBUG) { + needs_debug_impl = ctx.options().derive_debug && + ctx.options().impl_debug && + !ctx.no_debug_by_name(item) && + !item.annotations().disallow_debug(); + } + + if !derivable_traits.contains(DerivableTraits::DEFAULT) { + needs_default_impl = ctx.options().derive_default && + !self.is_forward_declaration() && + !ctx.no_default_by_name(item) && + !item.annotations().disallow_default(); + } + + let all_template_params = item.all_template_params(ctx); + + if derivable_traits.contains(DerivableTraits::COPY) && + !derivable_traits.contains(DerivableTraits::CLONE) + { + needs_clone_impl = true; + } + + if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) { + needs_partialeq_impl = ctx.options().derive_partialeq && + ctx.options().impl_partialeq && + ctx.lookup_can_derive_partialeq_or_partialord(item.id()) == + CanDerive::Manually; + } + + let mut derives: Vec<_> = derivable_traits.into(); + derives.extend(item.annotations().derives().iter().map(String::as_str)); + + let is_rust_union = is_union && struct_layout.is_rust_union(); + + utils::call_discovered_item_callback(ctx, item, || match self.kind() { + CompKind::Struct => DiscoveredItem::Struct { + original_name: item + .kind() + .expect_type() + .name() + .map(String::from), + final_name: canonical_ident.to_string(), + }, + CompKind::Union => DiscoveredItem::Union { + original_name: item + .kind() + .expect_type() + .name() + .map(String::from), + final_name: canonical_ident.to_string(), + }, + }); + + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives = ctx.options().all_callbacks(|cb| { + cb.add_derives(&DeriveInfo { + name: &canonical_name, + kind: if is_rust_union { + DeriveTypeKind::Union + } else { + DeriveTypeKind::Struct + }, + }) + }); + // In most cases this will be a no-op, since custom_derives will be empty. + derives.extend(custom_derives.iter().map(|s| s.as_str())); + + if !derives.is_empty() { + attributes.push(attributes::derives(&derives)); + } + + attributes.extend( + item.annotations() + .attributes() + .iter() + .map(|s| s.parse().unwrap()), + ); + + let custom_attributes = ctx.options().all_callbacks(|cb| { + cb.add_attributes(&AttributeInfo { + name: &canonical_name, + kind: if is_rust_union { + DeriveTypeKind::Union + } else { + DeriveTypeKind::Struct + }, + }) + }); + attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap())); + + if item.must_use(ctx) { + attributes.push(attributes::must_use()); + } + + let mut tokens = if is_rust_union { + quote! { + #( #attributes )* + pub union #canonical_ident + } + } else { + quote! { + #( #attributes )* + pub struct #canonical_ident + } + }; + + tokens.append_all(quote! { + #generics { + #( #fields )* + } + }); + result.push(tokens); + + // Generate the inner types and all that stuff. + // + // TODO: In the future we might want to be smart, and use nested + // modules, and whatnot. + for ty in self.inner_types() { + let child_item = ctx.resolve_item(*ty); + // assert_eq!(child_item.parent_id(), item.id()); + child_item.codegen(ctx, result, &()); + } + + // NOTE: Some unexposed attributes (like alignment attributes) may + // affect layout, so we're bad and pray to the gods for avoid sending + // all the tests to shit when parsing things like max_align_t. + if self.found_unknown_attr() { + warn!("Type {canonical_ident} has an unknown attribute that may affect layout"); + } + + if all_template_params.is_empty() { + if !is_opaque { + for var in self.inner_vars() { + ctx.resolve_item(*var).codegen(ctx, result, &()); + } + } + + if ctx.options().layout_tests && !self.is_forward_declaration() { + if let Some(layout) = layout { + let compile_time = ctx.options().rust_features().offset_of; + let fn_name = if compile_time { + None + } else { + let fn_name = + format!("bindgen_test_layout_{canonical_ident}"); + Some(ctx.rust_ident_raw(fn_name)) + }; + let prefix = ctx.trait_prefix(); + let size_of_expr = quote! { + ::#prefix::mem::size_of::<#canonical_ident>() + }; + let align_of_expr = quote! { + ::#prefix::mem::align_of::<#canonical_ident>() + }; + let size = layout.size; + let align = layout.align; + let size_of_err = format!("Size of {canonical_ident}"); + let align_of_err = + format!("Alignment of {canonical_ident}"); + + let check_struct_align = if compile_time { + quote! { + [#align_of_err][#align_of_expr - #align]; + } + } else { + quote! { + assert_eq!(#align_of_expr, #align, #align_of_err); + } + }; + + let should_skip_field_offset_checks = is_opaque; + + let check_field_offset = if should_skip_field_offset_checks + { + vec![] + } else { + self.fields() + .iter() + .filter_map(|field| { + let Field::DataMember(field) = field else { return None }; + let name = field.name()?; + field.offset().map(|offset| { + let field_offset = offset / 8; + let field_name = ctx.rust_ident(name); + let offset_of_err = format!("Offset of field: {canonical_ident}::{field_name}"); + if compile_time { + quote! { + [#offset_of_err][ + ::#prefix::mem::offset_of!(#canonical_ident, #field_name) - #field_offset + ]; + } + } else { + quote! { + assert_eq!( + unsafe { + ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize + }, + #field_offset, + #offset_of_err + ); + } + } + }) + }) + .collect() + }; + + let uninit_decl = if check_field_offset.is_empty() || + compile_time + { + None + } else { + // FIXME: When MSRV >= 1.59.0, we can use + // > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr(); + Some(quote! { + // Use a shared MaybeUninit so that rustc with + // opt-level=0 doesn't take too much stack space, + // see #2218. + const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + }) + }; + + if compile_time { + result.push(quote! { + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [#size_of_err][#size_of_expr - #size]; + #check_struct_align + #( #check_field_offset )* + }; + }); + } else { + result.push(quote! { + #[test] + fn #fn_name() { + #uninit_decl + assert_eq!(#size_of_expr, #size, #size_of_err); + #check_struct_align + #( #check_field_offset )* + } + }); + } + } + } + + let mut method_names = Default::default(); + let discovered_id = DiscoveredItemId::new(item.id().as_usize()); + if ctx.options().codegen_config.methods() { + for method in self.methods() { + assert_ne!(method.kind(), MethodKind::Constructor); + method.codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + discovered_id, + ); + } + } + + if ctx.options().codegen_config.constructors() { + for sig in self.constructors() { + Method::new( + MethodKind::Constructor, + *sig, + /* const */ + false, + ) + .codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + discovered_id, + ); + } + } + + if ctx.options().codegen_config.destructors() { + if let Some((kind, destructor)) = self.destructor() { + debug_assert!(kind.is_destructor()); + Method::new(kind, destructor, false).codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + discovered_id, + ); + } + } + } + + // NB: We can't use to_rust_ty here since for opaque types this tries to + // use the specialization knowledge to generate a blob field. + let ty_for_impl = quote! { + #canonical_ident #impl_generics_params + }; + + if needs_clone_impl { + result.push(quote! { + impl #impl_generics_labels Clone for #ty_for_impl { + fn clone(&self) -> Self { *self } + } + }); + } + + if needs_flexarray_impl { + result.push(self.generate_flexarray( + ctx, + &canonical_ident, + flex_inner_ty.as_ref(), + &generic_param_names, + &impl_generics_labels, + )); + } + + if needs_default_impl { + let prefix = ctx.trait_prefix(); + let body = quote! { + let mut s = ::#prefix::mem::MaybeUninit::::uninit(); + unsafe { + ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + }; + // Note we use `ptr::write_bytes()` instead of `mem::zeroed()` because the latter does + // not necessarily ensure padding bytes are zeroed. Some C libraries are sensitive to + // non-zero padding bytes, especially when forwards/backwards compatibility is + // involved. + result.push(quote! { + impl #impl_generics_labels Default for #ty_for_impl { + fn default() -> Self { + #body + } + } + }); + } + + if needs_debug_impl { + let impl_ = impl_debug::gen_debug_impl( + ctx, + self.fields(), + item, + self.kind(), + ); + + let prefix = ctx.trait_prefix(); + + result.push(quote! { + impl #impl_generics_labels ::#prefix::fmt::Debug for #ty_for_impl { + #impl_ + } + }); + } + + if needs_partialeq_impl { + if let Some(impl_) = impl_partialeq::gen_partialeq_impl( + ctx, + self, + item, + &ty_for_impl, + ) { + let partialeq_bounds = if generic_param_names.is_empty() { + quote! {} + } else { + let bounds = generic_param_names.iter().map(|t| { + quote! { #t: PartialEq } + }); + quote! { where #( #bounds ),* } + }; + + let prefix = ctx.trait_prefix(); + result.push(quote! { + impl #impl_generics_labels ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds { + #impl_ + } + }); + } + } + + if !methods.is_empty() { + result.push(quote! { + impl #impl_generics_labels #ty_for_impl { + #( #methods )* + } + }); + } + } +} + +impl CompInfo { + fn generate_flexarray( + &self, + ctx: &BindgenContext, + canonical_ident: &Ident, + flex_inner_ty: Option<&proc_macro2::TokenStream>, + generic_param_names: &[Ident], + impl_generics_labels: &proc_macro2::TokenStream, + ) -> proc_macro2::TokenStream { + let prefix = ctx.trait_prefix(); + + let flex_array = flex_inner_ty.as_ref().map(|ty| quote! { [ #ty ] }); + + let dst_ty_for_impl = quote! { + #canonical_ident < #( #generic_param_names , )* #flex_array > + + }; + let sized_ty_for_impl = quote! { + #canonical_ident < #( #generic_param_names , )* [ #flex_inner_ty; 0 ] > + }; + + let layout = if ctx.options().rust_features().layout_for_ptr { + quote! { + pub fn layout(len: usize) -> ::#prefix::alloc::Layout { + // SAFETY: Null pointers are OK if we don't deref them + unsafe { + let p: *const Self = ::#prefix::ptr::from_raw_parts(::#prefix::ptr::null::<()>(), len); + ::#prefix::alloc::Layout::for_value_raw(p) + } + } + } + } else { + quote!() + }; + + let (from_ptr_dst, from_ptr_sized) = if ctx + .options() + .rust_features() + .ptr_metadata + { + let flex_ref_inner = ctx.wrap_unsafe_ops(quote! { + Self::flex_ptr(self, len) + }); + let flex_ref_mut_inner = ctx.wrap_unsafe_ops(quote! { + Self::flex_ptr_mut(self, len).assume_init() + }); + let flex_ptr_inner = ctx.wrap_unsafe_ops(quote! { + &*::#prefix::ptr::from_raw_parts(ptr as *const (), len) + }); + let flex_ptr_mut_inner = ctx.wrap_unsafe_ops(quote! { + // Initialize reference without ever exposing it, as its possibly uninitialized + let mut uninit = ::#prefix::mem::MaybeUninit::<&mut #dst_ty_for_impl>::uninit(); + (uninit.as_mut_ptr() as *mut *mut #dst_ty_for_impl) + .write(::#prefix::ptr::from_raw_parts_mut(ptr as *mut (), len)); + + uninit + }); + + ( + quote! { + #[inline] + pub fn fixed(&self) -> (& #sized_ty_for_impl, usize) { + unsafe { + let (ptr, len) = (self as *const Self).to_raw_parts(); + (&*(ptr as *const #sized_ty_for_impl), len) + } + } + + #[inline] + pub fn fixed_mut(&mut self) -> (&mut #sized_ty_for_impl, usize) { + unsafe { + let (ptr, len) = (self as *mut Self).to_raw_parts(); + (&mut *(ptr as *mut #sized_ty_for_impl), len) + } + } + }, + quote! { + /// Convert a sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + pub unsafe fn flex_ref(&self, len: usize) -> &#dst_ty_for_impl { + // SAFETY: Reference is always valid as pointer. Caller is guaranteeing `len`. + #flex_ref_inner + } + + /// Convert a mutable sized prefix to an unsized structure with the given length. + /// + /// SAFETY: Underlying storage is initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ref_mut(&mut self, len: usize) -> &mut #dst_ty_for_impl { + // SAFETY: Reference is always valid as pointer. Caller is guaranteeing `len`. + #flex_ref_mut_inner + } + + /// Construct DST variant from a pointer and a size. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements. + #[inline] + pub unsafe fn flex_ptr<'unbounded>(ptr: *const Self, len: usize) -> &'unbounded #dst_ty_for_impl { + #flex_ptr_inner + } + + /// Construct mutable DST variant from a pointer and a + /// size. The returned `&mut` reference is initialized + /// pointing to memory referenced by `ptr`, but there's + /// no requirement that that memory be initialized. + /// + /// NOTE: lifetime of returned reference is not tied to any underlying storage. + /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements. + #[inline] + pub unsafe fn flex_ptr_mut<'unbounded>( + ptr: *mut Self, + len: usize, + ) -> ::#prefix::mem::MaybeUninit<&'unbounded mut #dst_ty_for_impl> { + #flex_ptr_mut_inner + } + }, + ) + } else { + (quote!(), quote!()) + }; + + quote! { + impl #impl_generics_labels #dst_ty_for_impl { + #layout + #from_ptr_dst + } + + impl #impl_generics_labels #sized_ty_for_impl { + #from_ptr_sized + } + } + } +} + +impl Method { + fn codegen_method( + &self, + ctx: &BindgenContext, + methods: &mut Vec, + method_names: &mut HashSet, + result: &mut CodegenResult<'_>, + _parent: &CompInfo, + parent_id: DiscoveredItemId, + ) { + assert!({ + let cc = &ctx.options().codegen_config; + match self.kind() { + MethodKind::Constructor => cc.constructors(), + MethodKind::Destructor | + MethodKind::VirtualDestructor { .. } => cc.destructors(), + MethodKind::Static | + MethodKind::Normal | + MethodKind::Virtual { .. } => cc.methods(), + } + }); + + // TODO(emilio): We could generate final stuff at least. + if self.is_virtual() { + return; // FIXME + } + + // First of all, output the actual function. + let function_item = ctx.resolve_item(self.signature()); + if !function_item.process_before_codegen(ctx, result) { + return; + } + let function = function_item.expect_function(); + let times_seen = function.codegen(ctx, result, function_item); + let Some(times_seen) = times_seen else { return }; + let signature_item = ctx.resolve_item(function.signature()); + let mut name = match self.kind() { + MethodKind::Constructor => "new".into(), + MethodKind::Destructor => "destruct".into(), + _ => function.name().to_owned(), + }; + + let TypeKind::Function(ref signature) = + *signature_item.expect_type().kind() + else { + panic!("How in the world?") + }; + + let supported_abi = signature.abi(ctx, Some(&*name)).is_ok(); + if !supported_abi { + return; + } + + // Do not generate variadic methods, since rust does not allow + // implementing them, and we don't do a good job at it anyway. + if signature.is_variadic() { + return; + } + + if method_names.contains(&name) { + let mut count = 1; + let mut new_name; + + while { + new_name = format!("{name}{count}"); + method_names.contains(&new_name) + } { + count += 1; + } + + name = new_name; + } + + method_names.insert(name.clone()); + + utils::call_discovered_item_callback(ctx, function_item, || { + DiscoveredItem::Method { + parent: parent_id, + final_name: name.clone(), + } + }); + + let mut function_name = function_item.canonical_name(ctx); + if times_seen > 0 { + write!(&mut function_name, "{times_seen}").unwrap(); + } + let function_name = ctx.rust_ident(function_name); + let mut args = utils::fnsig_arguments(ctx, signature); + let mut ret = utils::fnsig_return_ty(ctx, signature); + + if !self.is_static() && !self.is_constructor() { + args[0] = if self.is_const() { + quote! { &self } + } else { + quote! { &mut self } + }; + } + + // If it's a constructor, we always return `Self`, and we inject the + // "this" parameter, so there's no need to ask the user for it. + // + // Note that constructors in Clang are represented as functions with + // return-type = void. + if self.is_constructor() { + args.remove(0); + ret = quote! { -> Self }; + } + + let mut exprs = + helpers::ast_ty::arguments_from_signature(signature, ctx); + + let mut stmts = vec![]; + + // If it's a constructor, we need to insert an extra parameter with a + // variable called `__bindgen_tmp` we're going to create. + if self.is_constructor() { + let prefix = ctx.trait_prefix(); + exprs[0] = quote! { + __bindgen_tmp.as_mut_ptr() + }; + let tmp_variable_decl = quote! { + let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit() + }; + stmts.push(tmp_variable_decl); + } else if !self.is_static() { + assert!(!exprs.is_empty()); + exprs[0] = quote! { + self + }; + } + + let call = quote! { + #function_name (#( #exprs ),* ) + }; + + stmts.push(call); + + if self.is_constructor() { + stmts.push(quote! { + __bindgen_tmp.assume_init() + }); + } + + let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*)); + + let mut attrs = vec![attributes::inline()]; + + if signature.must_use() { + attrs.push(attributes::must_use()); + } + + let name = ctx.rust_ident(&name); + methods.push(quote! { + #(#attrs)* + pub unsafe fn #name ( #( #args ),* ) #ret { + #block + } + }); + } +} + +/// A helper type that represents different enum variations. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] +pub enum EnumVariation { + /// The code for this enum will use a Rust enum. Note that creating this in unsafe code + /// (including FFI) with an invalid value will invoke undefined behaviour, whether or not + /// its marked as `#[non_exhaustive]`. + Rust { + /// Indicates whether the generated struct should be `#[non_exhaustive]` + non_exhaustive: bool, + }, + /// The code for this enum will use a newtype + NewType { + /// Indicates whether the newtype will have bitwise operators + is_bitfield: bool, + /// Indicates whether the variants will be represented as global constants + is_global: bool, + }, + /// The code for this enum will use consts + #[default] + Consts, + /// The code for this enum will use a module containing consts + ModuleConsts, +} + +impl EnumVariation { + fn is_rust(self) -> bool { + matches!(self, EnumVariation::Rust { .. }) + } + + /// Both the `Const` and `ModuleConsts` variants will cause this to return + /// true. + fn is_const(self) -> bool { + matches!(self, EnumVariation::Consts | EnumVariation::ModuleConsts) + } +} + +impl fmt::Display for EnumVariation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::Rust { + non_exhaustive: false, + } => "rust", + Self::Rust { + non_exhaustive: true, + } => "rust_non_exhaustive", + Self::NewType { + is_bitfield: true, .. + } => "bitfield", + Self::NewType { + is_bitfield: false, + is_global, + } => { + if *is_global { + "newtype_global" + } else { + "newtype" + } + } + Self::Consts => "consts", + Self::ModuleConsts => "moduleconsts", + }; + s.fmt(f) + } +} + +impl FromStr for EnumVariation { + type Err = std::io::Error; + + /// Create a `EnumVariation` from a string. + fn from_str(s: &str) -> Result { + match s { + "rust" => Ok(EnumVariation::Rust { + non_exhaustive: false, + }), + "rust_non_exhaustive" => Ok(EnumVariation::Rust { + non_exhaustive: true, + }), + "bitfield" => Ok(EnumVariation::NewType { + is_bitfield: true, + is_global: false, + }), + "consts" => Ok(EnumVariation::Consts), + "moduleconsts" => Ok(EnumVariation::ModuleConsts), + "newtype" => Ok(EnumVariation::NewType { + is_bitfield: false, + is_global: false, + }), + "newtype_global" => Ok(EnumVariation::NewType { + is_bitfield: false, + is_global: true, + }), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + concat!( + "Got an invalid EnumVariation. Accepted values ", + "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',", + "'moduleconsts', 'newtype' and 'newtype_global'." + ), + )), + } + } +} + +struct EnumBuilder { + /// Type identifier of the enum. + /// + /// This is the base name, i.e. for `ModuleConst` enums, this does not include the module name. + enum_type: Ident, + /// Attributes applying to the enum type + attrs: Vec, + /// The representation of the enum, e.g. `u32`. + repr: syn::Type, + /// The enum kind we are generating + kind: EnumBuilderKind, + /// A list of all variants this enum has. + enum_variants: Vec, +} + +/// A helper type to construct different enum variations. +enum EnumBuilderKind { + Rust { + non_exhaustive: bool, + }, + NewType { + is_bitfield: bool, + is_global: bool, + /// if the enum is named or not. + is_anonymous: bool, + }, + Consts { + needs_typedef: bool, + }, + ModuleConsts { + module_name: Ident, + }, +} + +impl EnumBuilder { + /// Returns true if the builder is for a rustified enum. + fn is_rust_enum(&self) -> bool { + matches!(self.kind, EnumBuilderKind::Rust { .. }) + } + + /// Create a new enum given an item builder, a canonical name, a name for + /// the representation, and which variation it should be generated as. + fn new( + name: &str, + attrs: Vec, + repr: &syn::Type, + enum_variation: EnumVariation, + has_typedef: bool, + enum_is_anonymous: bool, + ) -> Self { + let ident = Ident::new(name, Span::call_site()); + // For most variants this is the same + let mut enum_ty = ident.clone(); + + let kind = match enum_variation { + EnumVariation::NewType { + is_bitfield, + is_global, + } => EnumBuilderKind::NewType { + is_bitfield, + is_global, + is_anonymous: enum_is_anonymous, + }, + + EnumVariation::Rust { non_exhaustive } => { + EnumBuilderKind::Rust { non_exhaustive } + } + + EnumVariation::Consts => EnumBuilderKind::Consts { + needs_typedef: !has_typedef, + }, + + EnumVariation::ModuleConsts => { + enum_ty = Ident::new( + CONSTIFIED_ENUM_MODULE_REPR_NAME, + Span::call_site(), + ); + + EnumBuilderKind::ModuleConsts { + module_name: ident.clone(), + } + } + }; + EnumBuilder { + enum_type: enum_ty, + attrs, + repr: repr.clone(), + kind, + enum_variants: vec![], + } + } + + /// Add a variant to this enum. + fn with_variant( + mut self, + ctx: &BindgenContext, + variant: &EnumVariant, + variant_doc: proc_macro2::TokenStream, + mangling_prefix: Option<&str>, + rust_ty: &syn::Type, + is_ty_named: bool, + ) -> Self { + let variant_name = ctx.rust_mangle(variant.name()); + let is_rust_enum = self.is_rust_enum(); + let expr = match variant.val() { + EnumVariantValue::Boolean(v) if is_rust_enum => { + helpers::ast_ty::uint_expr(u64::from(v)) + } + EnumVariantValue::Boolean(v) => quote!(#v), + EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), + EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v), + }; + + match self.kind { + EnumBuilderKind::Rust { .. } => { + let name = ctx.rust_ident(variant_name); + self.enum_variants.push(EnumVariantInfo { + variant_name: name, + variant_doc, + value: expr, + }); + self + } + + EnumBuilderKind::NewType { is_global, .. } => { + let variant_ident = if is_ty_named && !is_global { + ctx.rust_ident(variant_name) + } else { + ctx.rust_ident(match mangling_prefix { + Some(prefix) => { + Cow::Owned(format!("{prefix}_{variant_name}")) + } + None => variant_name, + }) + }; + self.enum_variants.push(EnumVariantInfo { + variant_name: variant_ident, + variant_doc, + value: quote! { #rust_ty ( #expr )}, + }); + + self + } + + EnumBuilderKind::Consts { .. } => { + let constant_name = match mangling_prefix { + Some(prefix) => { + Cow::Owned(format!("{prefix}_{variant_name}")) + } + None => variant_name, + }; + + let ident = ctx.rust_ident(constant_name); + self.enum_variants.push(EnumVariantInfo { + variant_name: ident, + variant_doc, + value: quote! { #expr }, + }); + + self + } + EnumBuilderKind::ModuleConsts { .. } => { + let name = ctx.rust_ident(variant_name); + self.enum_variants.push(EnumVariantInfo { + variant_name: name, + variant_doc, + value: quote! { #expr }, + }); + self + } + } + } + + fn newtype_bitfield_impl( + prefix: &Ident, + rust_ty: &syn::Type, + ) -> proc_macro2::TokenStream { + let rust_ty_name = &rust_ty; + quote! { + impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty { + type Output = Self; + + #[inline] + fn bitor(self, other: Self) -> Self { + #rust_ty_name(self.0 | other.0) + } + } + impl ::#prefix::ops::BitOrAssign for #rust_ty { + #[inline] + fn bitor_assign(&mut self, rhs: #rust_ty) { + self.0 |= rhs.0; + } + } + impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty { + type Output = Self; + + #[inline] + fn bitand(self, other: Self) -> Self { + #rust_ty_name(self.0 & other.0) + } + } + impl ::#prefix::ops::BitAndAssign for #rust_ty { + #[inline] + fn bitand_assign(&mut self, rhs: #rust_ty) { + self.0 &= rhs.0; + } + } + } + } + + fn build( + self, + ctx: &BindgenContext, + rust_ty: &syn::Type, + ) -> proc_macro2::TokenStream { + let enum_ident = self.enum_type; + + // 1. Construct a list of the enum variants + let variants = match self.kind { + EnumBuilderKind::Rust { .. } => { + let mut variants = vec![]; + + for v in self.enum_variants { + let variant_doc = &v.variant_doc; + let variant_ident = &v.variant_name; + let variant_value = &v.value; + + variants.push(quote! { + #variant_doc + #variant_ident = #variant_value, + }); + } + + if variants.is_empty() { + variants.push( + quote! {__bindgen_cannot_repr_c_on_empty_enum = 0,}, + ); + } + variants + } + EnumBuilderKind::NewType { .. } => { + let mut variants = vec![]; + + for v in self.enum_variants { + let variant_doc = &v.variant_doc; + let variant_ident = &v.variant_name; + let variant_value = &v.value; + + variants.push(quote! { + #variant_doc + pub const #variant_ident: #enum_ident = #variant_value; + }); + } + variants + } + EnumBuilderKind::Consts { .. } | + EnumBuilderKind::ModuleConsts { .. } => { + let mut variants = vec![]; + + for v in self.enum_variants { + let variant_doc = &v.variant_doc; + let variant_ident = &v.variant_name; + let variant_value = &v.value; + + variants.push(quote! { + #variant_doc + pub const #variant_ident: #enum_ident = #variant_value; + }); + } + variants + } + }; + let attrs = self.attrs; + let enum_repr = &self.repr; + + // 2. Generate the enum representation + match self.kind { + EnumBuilderKind::Rust { non_exhaustive } => { + let non_exhaustive_opt = + non_exhaustive.then(attributes::non_exhaustive); + + quote! { + // Note: repr is on top of attrs to keep the test expectations diff small. + // a future commit could move it further down. + #[repr(#enum_repr)] + #non_exhaustive_opt + #( #attrs )* + pub enum #enum_ident { + #( #variants )* + } + } + } + EnumBuilderKind::NewType { + is_bitfield, + is_global, + is_anonymous, + } => { + // There doesn't seem to be a technical reason why we generate + // anon enum variants as global constants. + // We keep this behavior to avoid breaking changes in the bindings. + let impl_variants = if is_anonymous || is_global { + quote! { + #( #variants )* + } + } else { + quote! { + impl #enum_ident { + #( #variants )* + } + } + }; + + let prefix = ctx.trait_prefix(); + let bitfield_impl_opt = is_bitfield + .then(|| Self::newtype_bitfield_impl(&prefix, rust_ty)); + + quote! { + // Previously variant impls where before the enum definition. + // lets keep this as is for now, to reduce the diff in generated bindings. + #impl_variants + + #bitfield_impl_opt + + #[repr(transparent)] + #( #attrs )* + pub struct #enum_ident (pub #enum_repr); + } + } + EnumBuilderKind::Consts { needs_typedef } => { + let typedef_opt = needs_typedef.then(|| { + quote! { + #( #attrs )* + pub type #enum_ident = #enum_repr; + } + }); + quote! { + #( #variants )* + + #typedef_opt + } + } + EnumBuilderKind::ModuleConsts { module_name, .. } => { + quote! { + // todo: Probably some attributes, e.g. `cfg` should apply to the `mod`. + pub mod #module_name { + #[allow(unused_imports)] + use super::*; + + #( #attrs )* + pub type #enum_ident = #enum_repr; + + #( #variants )* + } + } + } + } + } +} + +impl CodeGenerator for Enum { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug!("::codegen: item = {item:?}"); + debug_assert!(item.is_enabled_for_codegen(ctx)); + + let name = item.canonical_name(ctx); + let ident = ctx.rust_ident(&name); + let enum_ty = item.expect_type(); + let layout = enum_ty.layout(ctx); + let variation = self.computed_enum_variation(ctx, item); + + let repr_translated; + let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) { + Some(repr) + if !ctx.options().translate_enum_integer_types && + !variation.is_rust() => + { + repr + } + repr => { + // An enum's integer type is translated to a native Rust + // integer type in 3 cases: + // * the enum is Rustified and we need a translated type for + // the repr attribute + // * the representation couldn't be determined from the C source + // * it was explicitly requested as a bindgen option + + let kind = if let Some(repr) = repr { + match *repr.canonical_type(ctx).kind() { + TypeKind::Int(int_kind) => int_kind, + _ => panic!("Unexpected type as enum repr"), + } + } else { + warn!( + "Guessing type of enum! Forward declarations of enums \ + shouldn't be legal!" + ); + IntKind::Int + }; + + let signed = kind.is_signed(); + let size = layout + .map(|l| l.size) + .or_else(|| kind.known_size()) + .unwrap_or(0); + + let translated = match (signed, size) { + (true, 1) => IntKind::I8, + (false, 1) => IntKind::U8, + (true, 2) => IntKind::I16, + (false, 2) => IntKind::U16, + (true, 4) => IntKind::I32, + (false, 4) => IntKind::U32, + (true, 8) => IntKind::I64, + (false, 8) => IntKind::U64, + _ => { + warn!( + "invalid enum decl: signed: {signed}, size: {size}" + ); + IntKind::I32 + } + }; + + repr_translated = + Type::new(None, None, TypeKind::Int(translated), false); + &repr_translated + } + }; + + let mut attrs = vec![]; + + if let Some(comment) = item.comment(ctx) { + attrs.push(attributes::doc(&comment)); + } + + if item.must_use(ctx) { + attrs.push(attributes::must_use()); + } + + if !variation.is_const() { + let packed = false; // Enums can't be packed in Rust. + let mut derives = derives_of_item(item, ctx, packed); + // For backwards compat, enums always derive + // Clone/Eq/PartialEq/Hash, even if we don't generate those by + // default. + derives.insert( + DerivableTraits::CLONE | + DerivableTraits::HASH | + DerivableTraits::PARTIAL_EQ | + DerivableTraits::EQ, + ); + let mut derives: Vec<_> = derives.into(); + for derive in item.annotations().derives() { + if !derives.contains(&derive.as_str()) { + derives.push(derive); + } + } + + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives = ctx.options().all_callbacks(|cb| { + cb.add_derives(&DeriveInfo { + name: &name, + kind: DeriveTypeKind::Enum, + }) + }); + // In most cases this will be a no-op, since custom_derives will be empty. + derives.extend(custom_derives.iter().map(|s| s.as_str())); + + attrs.extend( + item.annotations() + .attributes() + .iter() + .map(|s| s.parse().unwrap()), + ); + + // The custom attribute callback may return a list of attributes; + // add them to the end of the list. + let custom_attributes = ctx.options().all_callbacks(|cb| { + cb.add_attributes(&AttributeInfo { + name: &name, + kind: DeriveTypeKind::Enum, + }) + }); + attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap())); + + attrs.push(attributes::derives(&derives)); + } + + fn add_constant( + ctx: &BindgenContext, + enum_: &Type, + // Only to avoid recomputing every time. + enum_canonical_name: &Ident, + // May be the same as "variant" if it's because the + // enum is unnamed and we still haven't seen the + // value. + variant_name: &Ident, + referenced_name: &Ident, + enum_rust_ty: &syn::Type, + result: &mut CodegenResult<'_>, + ) { + let constant_name = if enum_.name().is_some() { + if ctx.options().prepend_enum_name { + format!("{enum_canonical_name}_{variant_name}") + } else { + format!("{variant_name}") + } + } else { + format!("{variant_name}") + }; + let constant_name = ctx.rust_ident(constant_name); + + result.push(quote! { + pub const #constant_name : #enum_rust_ty = + #enum_canonical_name :: #referenced_name ; + }); + } + + let repr = repr.to_rust_ty_or_opaque(ctx, item); + let has_typedef = ctx.is_enum_typedef_combo(item.id()); + + utils::call_discovered_item_callback(ctx, item, || { + DiscoveredItem::Enum { + final_name: name.clone(), + } + }); + + let mut builder = EnumBuilder::new( + &name, + attrs, + &repr, + variation, + has_typedef, + enum_ty.name().is_none(), + ); + + // A map where we keep a value -> variant relation. + let mut seen_values = HashMap::<_, Ident>::default(); + let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &()); + let is_toplevel = item.is_toplevel(ctx); + + // Used to mangle the constants we generate in the unnamed-enum case. + let parent_canonical_name = if is_toplevel { + None + } else { + Some(item.parent_id().canonical_name(ctx)) + }; + + let constant_mangling_prefix = if ctx.options().prepend_enum_name { + if enum_ty.name().is_none() { + parent_canonical_name.as_deref() + } else { + Some(&*name) + } + } else { + None + }; + + // NB: We defer the creation of constified variants, in case we find + // another variant with the same value (which is the common thing to + // do). + let mut constified_variants = VecDeque::new(); + + let mut iter = self.variants().iter().peekable(); + while let Some(variant) = + iter.next().or_else(|| constified_variants.pop_front()) + { + if variant.hidden() { + continue; + } + + if variant.force_constification() && iter.peek().is_some() { + constified_variants.push_back(variant); + continue; + } + + let mut variant_doc = quote! {}; + if ctx.options().generate_comments { + if let Some(raw_comment) = variant.comment() { + let processed_comment = + ctx.options().process_comment(raw_comment); + variant_doc = attributes::doc(&processed_comment); + } + } + + match seen_values.entry(variant.val()) { + Entry::Occupied(ref entry) => { + if variation.is_rust() { + let variant_name = ctx.rust_mangle(variant.name()); + let mangled_name = if is_toplevel || + enum_ty.name().is_some() + { + variant_name + } else { + let parent_name = + parent_canonical_name.as_ref().unwrap(); + + Cow::Owned(format!("{parent_name}_{variant_name}")) + }; + + let existing_variant_name = entry.get(); + // Use associated constants for named enums. + if enum_ty.name().is_some() { + let enum_canonical_name = &ident; + let variant_name = + ctx.rust_ident_raw(&*mangled_name); + result.push(quote! { + impl #enum_rust_ty { + pub const #variant_name : #enum_rust_ty = + #enum_canonical_name :: #existing_variant_name ; + } + }); + } else { + add_constant( + ctx, + enum_ty, + &ident, + &Ident::new(&mangled_name, Span::call_site()), + existing_variant_name, + &enum_rust_ty, + result, + ); + } + } else { + builder = builder.with_variant( + ctx, + variant, + variant_doc, + constant_mangling_prefix, + &enum_rust_ty, + enum_ty.name().is_some(), + ); + } + } + Entry::Vacant(entry) => { + builder = builder.with_variant( + ctx, + variant, + variant_doc, + constant_mangling_prefix, + &enum_rust_ty, + enum_ty.name().is_some(), + ); + + let variant_name = ctx.rust_ident(variant.name()); + + // If it's an unnamed enum, or constification is enforced, + // we also generate a constant so it can be properly + // accessed. + if (variation.is_rust() && enum_ty.name().is_none()) || + variant.force_constification() + { + let mangled_name = if is_toplevel { + variant_name.clone() + } else { + let parent_name = + parent_canonical_name.as_ref().unwrap(); + + Ident::new( + &format!("{parent_name}_{variant_name}"), + Span::call_site(), + ) + }; + + add_constant( + ctx, + enum_ty, + &ident, + &mangled_name, + &variant_name, + &enum_rust_ty, + result, + ); + } + + entry.insert(variant_name); + } + } + } + + let item = builder.build(ctx, &enum_rust_ty); + result.push(item); + } +} + +struct EnumVariantInfo { + variant_name: Ident, + variant_doc: proc_macro2::TokenStream, + value: proc_macro2::TokenStream, +} + +/// Enum for the default type of macro constants. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] +pub enum MacroTypeVariation { + /// Use i32 or i64 + Signed, + /// Use u32 or u64 + #[default] + Unsigned, +} + +impl fmt::Display for MacroTypeVariation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::Signed => "signed", + Self::Unsigned => "unsigned", + }; + s.fmt(f) + } +} + +impl FromStr for MacroTypeVariation { + type Err = std::io::Error; + + /// Create a `MacroTypeVariation` from a string. + fn from_str(s: &str) -> Result { + match s { + "signed" => Ok(MacroTypeVariation::Signed), + "unsigned" => Ok(MacroTypeVariation::Unsigned), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + concat!( + "Got an invalid MacroTypeVariation. Accepted values ", + "are 'signed' and 'unsigned'" + ), + )), + } + } +} + +/// Enum for how aliases should be translated. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] +pub enum AliasVariation { + /// Convert to regular Rust alias + #[default] + TypeAlias, + /// Create a new type by wrapping the old type in a struct and using #[repr(transparent)] + NewType, + /// Same as `NewType` but also impl Deref to be able to use the methods of the wrapped type + NewTypeDeref, +} + +impl fmt::Display for AliasVariation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::TypeAlias => "type_alias", + Self::NewType => "new_type", + Self::NewTypeDeref => "new_type_deref", + }; + + s.fmt(f) + } +} + +impl FromStr for AliasVariation { + type Err = std::io::Error; + + /// Create an `AliasVariation` from a string. + fn from_str(s: &str) -> Result { + match s { + "type_alias" => Ok(AliasVariation::TypeAlias), + "new_type" => Ok(AliasVariation::NewType), + "new_type_deref" => Ok(AliasVariation::NewTypeDeref), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + concat!( + "Got an invalid AliasVariation. Accepted values ", + "are 'type_alias', 'new_type', and 'new_type_deref'" + ), + )), + } + } +} + +/// Enum for how non-`Copy` `union`s should be translated. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum NonCopyUnionStyle { + /// Wrap members in a type generated by `bindgen`. + BindgenWrapper, + /// Wrap members in [`::core::mem::ManuallyDrop`]. + /// + /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your + /// MSRV is lower. + ManuallyDrop, +} + +impl fmt::Display for NonCopyUnionStyle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::BindgenWrapper => "bindgen_wrapper", + Self::ManuallyDrop => "manually_drop", + }; + + s.fmt(f) + } +} + +impl Default for NonCopyUnionStyle { + fn default() -> Self { + Self::BindgenWrapper + } +} + +impl FromStr for NonCopyUnionStyle { + type Err = std::io::Error; + + fn from_str(s: &str) -> Result { + match s { + "bindgen_wrapper" => Ok(Self::BindgenWrapper), + "manually_drop" => Ok(Self::ManuallyDrop), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + concat!( + "Got an invalid NonCopyUnionStyle. Accepted values ", + "are 'bindgen_wrapper' and 'manually_drop'" + ), + )), + } + } +} + +/// Fallible conversion to an opaque blob. +/// +/// Implementors of this trait should provide the `try_get_layout` method to +/// fallibly get this thing's layout, which the provided `try_to_opaque` trait +/// method will use to convert the `Layout` into an opaque blob Rust type. +pub(crate) trait TryToOpaque { + type Extra; + + /// Get the layout for this thing, if one is available. + fn try_get_layout( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result; + + /// Do not override this provided trait method. + fn try_to_opaque( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result { + self.try_get_layout(ctx, extra) + .map(|layout| helpers::blob(ctx, layout, true)) + } +} + +/// Infallible conversion of an IR thing to an opaque blob. +/// +/// The resulting layout is best effort, and is unfortunately not guaranteed to +/// be correct. When all else fails, we fall back to a single byte layout as a +/// last resort, because C++ does not permit zero-sized types. See the note in +/// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits +/// and when each is appropriate. +/// +/// Don't implement this directly. Instead implement `TryToOpaque`, and then +/// leverage the blanket impl for this trait. +pub(crate) trait ToOpaque: TryToOpaque { + fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout { + self.try_get_layout(ctx, extra) + .unwrap_or_else(|_| Layout::for_size(ctx, 1)) + } + + fn to_opaque( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> syn::Type { + let layout = self.get_layout(ctx, extra); + helpers::blob(ctx, layout, true) + } +} + +impl ToOpaque for T where T: TryToOpaque {} + +/// Fallible conversion from an IR thing to an *equivalent* Rust type. +/// +/// If the C/C++ construct represented by the IR thing cannot (currently) be +/// represented in Rust (for example, instantiations of templates with +/// const-value generic parameters) then the impl should return an `Err`. It +/// should *not* attempt to return an opaque blob with the correct size and +/// alignment. That is the responsibility of the `TryToOpaque` trait. +pub(crate) trait TryToRustTy { + type Extra; + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result; +} + +/// Fallible conversion to a Rust type or an opaque blob with the correct size +/// and alignment. +/// +/// Don't implement this directly. Instead implement `TryToRustTy` and +/// `TryToOpaque`, and then leverage the blanket impl for this trait below. +pub(crate) trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { + type Extra; + + fn try_to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &::Extra, + ) -> error::Result; +} + +impl TryToRustTyOrOpaque for T +where + T: TryToRustTy + TryToOpaque, +{ + type Extra = E; + + fn try_to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &E, + ) -> error::Result { + self.try_to_rust_ty(ctx, extra).or_else(|_| { + if let Ok(layout) = self.try_get_layout(ctx, extra) { + Ok(helpers::blob(ctx, layout, true)) + } else { + Err(Error::NoLayoutForOpaqueBlob) + } + }) + } +} + +/// Infallible conversion to a Rust type, or an opaque blob with a best effort +/// of correct size and alignment. +/// +/// Don't implement this directly. Instead implement `TryToRustTy` and +/// `TryToOpaque`, and then leverage the blanket impl for this trait below. +/// +/// ### Fallible vs. Infallible Conversions to Rust Types +/// +/// When should one use this infallible `ToRustTyOrOpaque` trait versus the +/// fallible `TryTo{RustTy, Opaque, RustTyOrOpaque}` traits? All fallible trait +/// implementations that need to convert another thing into a Rust type or +/// opaque blob in a nested manner should also use fallible trait methods and +/// propagate failure up the stack. Only infallible functions and methods like +/// `CodeGenerator` implementations should use the infallible +/// `ToRustTyOrOpaque`. The further out we push error recovery, the more likely +/// we are to get a usable `Layout` even if we can't generate an equivalent Rust +/// type for a C++ construct. +pub(crate) trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { + type Extra; + + fn to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &::Extra, + ) -> syn::Type; +} + +impl ToRustTyOrOpaque for T +where + T: TryToRustTy + ToOpaque, +{ + type Extra = E; + + fn to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &E, + ) -> syn::Type { + self.try_to_rust_ty(ctx, extra) + .unwrap_or_else(|_| self.to_opaque(ctx, extra)) + } +} + +impl TryToOpaque for T +where + T: Copy + Into, +{ + type Extra = (); + + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { + ctx.resolve_item((*self).into()).try_get_layout(ctx, &()) + } +} + +impl TryToRustTy for T +where + T: Copy + Into, +{ + type Extra = (); + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { + ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &()) + } +} + +impl TryToOpaque for Item { + type Extra = (); + + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { + self.kind().expect_type().try_get_layout(ctx, self) + } +} + +impl TryToRustTy for Item { + type Extra = (); + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { + self.kind().expect_type().try_to_rust_ty(ctx, self) + } +} + +impl TryToOpaque for Type { + type Extra = Item; + + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &Item, + ) -> error::Result { + self.layout(ctx).ok_or(Error::NoLayoutForOpaqueBlob) + } +} + +impl TryToRustTy for Type { + type Extra = Item; + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result { + use self::helpers::ast_ty::*; + + match *self.kind() { + TypeKind::Void => Ok(c_void(ctx)), + // TODO: we should do something smart with nullptr, or maybe *const + // c_void is enough? + TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)), + TypeKind::Int(ik) => { + Ok(int_kind_rust_type(ctx, ik, self.layout(ctx))) + } + TypeKind::Float(fk) => { + Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))) + } + TypeKind::Complex(fk) => { + let float_path = + float_kind_rust_type(ctx, fk, self.layout(ctx)); + + ctx.generated_bindgen_complex(); + Ok(if ctx.options().enable_cxx_namespaces { + syn::parse_quote! { root::__BindgenComplex<#float_path> } + } else { + syn::parse_quote! { __BindgenComplex<#float_path> } + }) + } + TypeKind::Function(ref signature) => { + // We can't rely on the sizeof(Option>) == + // sizeof(NonZero<_>) optimization with opaque blobs (because + // they aren't NonZero), so don't *ever* use an or_opaque + // variant here. + let ty = signature.try_to_rust_ty(ctx, item)?; + + let prefix = ctx.trait_prefix(); + Ok(syn::parse_quote! { ::#prefix::option::Option<#ty> }) + } + TypeKind::Array(item, len) | TypeKind::Vector(item, len) => { + let ty = item.try_to_rust_ty(ctx, &())?; + Ok(syn::parse_quote! { [ #ty ; #len ] }) + } + TypeKind::Enum(..) => { + let path = item.namespace_aware_canonical_path(ctx); + let path = proc_macro2::TokenStream::from_str(&path.join("::")) + .unwrap(); + Ok(syn::parse_quote!(#path)) + } + TypeKind::TemplateInstantiation(ref inst) => { + inst.try_to_rust_ty(ctx, item) + } + TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()), + TypeKind::TemplateAlias(..) | + TypeKind::Alias(..) | + TypeKind::BlockPointer(..) => { + if self.is_block_pointer() && !ctx.options().generate_block { + let void = c_void(ctx); + return Ok(void.to_ptr(/* is_const = */ false)); + } + + if item.is_opaque(ctx, &()) && + item.used_template_params(ctx) + .into_iter() + .any(|param| param.is_template_param(ctx, &())) + { + self.try_to_opaque(ctx, item) + } else if let Some(ty) = self + .name() + .and_then(|name| utils::type_from_named(ctx, name)) + { + Ok(ty) + } else { + utils::build_path(item, ctx) + } + } + TypeKind::Comp(ref info) => { + let template_params = item.all_template_params(ctx); + if info.has_non_type_template_params() || + (item.is_opaque(ctx, &()) && !template_params.is_empty()) + { + return self.try_to_opaque(ctx, item); + } + + utils::build_path(item, ctx) + } + TypeKind::Opaque => self.try_to_opaque(ctx, item), + TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { + // Check that this type has the same size as the target's pointer type. + let size = self.get_layout(ctx, item).size; + if size != ctx.target_pointer_size() { + return Err(Error::InvalidPointerSize { + ty_name: self.name().unwrap_or("unknown").into(), + ty_size: size, + ptr_size: ctx.target_pointer_size(), + }); + } + + let is_const = ctx.resolve_type(inner).is_const(); + + let inner = + inner.into_resolver().through_type_refs().resolve(ctx); + let inner_ty = inner.expect_type(); + + let is_objc_pointer = + matches!(inner_ty.kind(), TypeKind::ObjCInterface(..)); + + // Regardless if we can properly represent the inner type, we + // should always generate a proper pointer here, so use + // infallible conversion of the inner type. + let ty = inner + .to_rust_ty_or_opaque(ctx, &()) + .with_implicit_template_params(ctx, inner); + + // Avoid the first function pointer level, since it's already + // represented in Rust. + if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer + { + Ok(ty) + } else if ctx.options().generate_cxx_nonnull_references && + matches!(self.kind(), TypeKind::Reference(_)) + { + // It's UB to pass null values in place of C++ references + let prefix = ctx.trait_prefix(); + Ok(syn::parse_quote! { ::#prefix::ptr::NonNull<#ty> }) + } else { + Ok(ty.to_ptr(is_const)) + } + } + TypeKind::TypeParam => { + let name = item.canonical_name(ctx); + let ident = ctx.rust_ident(name); + Ok(syn::parse_quote! { #ident }) + } + TypeKind::ObjCSel => Ok(syn::parse_quote! { objc::runtime::Sel }), + TypeKind::ObjCId => Ok(syn::parse_quote! { id }), + TypeKind::ObjCInterface(ref interface) => { + let name = ctx.rust_ident(interface.name()); + Ok(syn::parse_quote! { #name }) + } + ref u @ TypeKind::UnresolvedTypeRef(..) => { + unreachable!("Should have been resolved after parsing {u:?}!") + } + } + } +} + +impl TryToOpaque for TemplateInstantiation { + type Extra = Item; + + fn try_get_layout( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result { + item.expect_type() + .layout(ctx) + .ok_or(Error::NoLayoutForOpaqueBlob) + } +} + +impl TryToRustTy for TemplateInstantiation { + type Extra = Item; + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result { + if self.is_opaque(ctx, item) { + return Err(Error::InstantiationOfOpaqueType); + } + + let def = self + .template_definition() + .into_resolver() + .through_type_refs() + .resolve(ctx); + + let mut ty = quote! {}; + let def_path = def.namespace_aware_canonical_path(ctx); + ty.append_separated( + def_path.into_iter().map(|p| ctx.rust_ident(p)), + quote!(::), + ); + + let def_params = def.self_template_params(ctx); + if def_params.is_empty() { + // This can happen if we generated an opaque type for a partial + // template specialization, and we've hit an instantiation of + // that partial specialization. + extra_assert!(def.is_opaque(ctx, &())); + return Err(Error::InstantiationOfOpaqueType); + } + + // TODO: If the definition type is a template class/struct + // definition's member template definition, it could rely on + // generic template parameters from its outer template + // class/struct. When we emit bindings for it, it could require + // *more* type arguments than we have here, and we will need to + // reconstruct them somehow. We don't have any means of doing + // that reconstruction at this time. + + let template_args = self + .template_arguments() + .iter() + .zip(def_params.iter()) + // Only pass type arguments for the type parameters that + // the def uses. + .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param)) + .map(|(arg, _)| { + let arg = arg.into_resolver().through_type_refs().resolve(ctx); + let ty = arg + .try_to_rust_ty(ctx, &())? + .with_implicit_template_params(ctx, arg); + Ok(ty) + }) + .collect::>>()?; + + Ok(if template_args.is_empty() { + syn::parse_quote! { #ty } + } else { + syn::parse_quote! { #ty<#(#template_args),*> } + }) + } +} + +impl TryToRustTy for FunctionSig { + type Extra = Item; + + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result { + // TODO: we might want to consider ignoring the reference return value. + let ret = utils::fnsig_return_ty(ctx, self); + let arguments = utils::fnsig_arguments(ctx, self); + + match self.abi(ctx, None) { + Ok(abi) => Ok( + syn::parse_quote! { unsafe extern #abi fn ( #( #arguments ),* ) #ret }, + ), + Err(err) => { + if matches!(err, Error::UnsupportedAbi(_)) { + unsupported_abi_diagnostic( + self.name(), + self.is_variadic(), + item.location(), + ctx, + &err, + ); + } + + Err(err) + } + } + } +} + +impl CodeGenerator for Function { + type Extra = Item; + + /// If we've actually generated the symbol, the number of times we've seen + /// it. + type Return = Option; + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) -> Self::Return { + debug!("::codegen: item = {item:?}"); + debug_assert!(item.is_enabled_for_codegen(ctx)); + + let is_internal = matches!(self.linkage(), Linkage::Internal); + + let signature_item = ctx.resolve_item(self.signature()); + let signature = signature_item.kind().expect_type().canonical_type(ctx); + let TypeKind::Function(ref signature) = *signature.kind() else { + panic!("Signature kind is not a Function: {signature:?}") + }; + + if is_internal { + if !ctx.options().wrap_static_fns { + // We cannot do anything with internal functions if we are not wrapping them so + // just avoid generating anything for them. + return None; + } + + if signature.is_variadic() { + // We cannot generate wrappers for variadic static functions so we avoid + // generating any code for them. + variadic_fn_diagnostic(self.name(), item.location(), ctx); + return None; + } + } + + let is_pure_virtual = match self.kind() { + FunctionKind::Method(ref method_kind) => { + method_kind.is_pure_virtual() + } + FunctionKind::Function => false, + }; + if is_pure_virtual && !ctx.options().generate_pure_virtual_functions { + // Pure virtual methods have no actual symbol, so we can't generate + // something meaningful for them. Downstream code postprocessors + // might want to find out about them. + return None; + } + + let is_dynamic_function = match self.kind() { + FunctionKind::Function => { + ctx.options().dynamic_library_name.is_some() + } + FunctionKind::Method(_) => false, + }; + + // Similar to static member variables in a class template, we can't + // generate bindings to template functions, because the set of + // instantiations is open ended and we have no way of knowing which + // monomorphizations actually exist. + if !item.all_template_params(ctx).is_empty() { + return None; + } + + let name = self.name(); + let mut canonical_name = item.canonical_name(ctx); + let mangled_name = self.mangled_name(); + + { + let seen_symbol_name = mangled_name.unwrap_or(&canonical_name); + + // TODO: Maybe warn here if there's a type/argument mismatch, or + // something? + if result.seen_function(seen_symbol_name) { + return None; + } + result.saw_function(seen_symbol_name); + } + + let mut attributes = vec![]; + + if true { + let must_use = signature.must_use() || { + let ret_ty = signature + .return_type() + .into_resolver() + .through_type_refs() + .resolve(ctx); + ret_ty.must_use(ctx) + }; + + if must_use { + attributes.push(attributes::must_use()); + } + } + + if let Some(comment) = item.comment(ctx) { + attributes.push(attributes::doc(&comment)); + } + + let abi = match signature.abi(ctx, Some(name)) { + Err(err) => { + if matches!(err, Error::UnsupportedAbi(_)) { + unsupported_abi_diagnostic( + name, + signature.is_variadic(), + item.location(), + ctx, + &err, + ); + } + + return None; + } + Ok(ClangAbi::Unknown(unknown_abi)) => { + panic!( + "Invalid or unknown abi {unknown_abi:?} for function {canonical_name:?} ({self:?})" + ); + } + Ok(abi) => abi, + }; + + // Handle overloaded functions by giving each overload its own unique + // suffix. + let times_seen = result.overload_number(&canonical_name); + if times_seen > 0 { + write!(&mut canonical_name, "{times_seen}").unwrap(); + } + utils::call_discovered_item_callback(ctx, item, || { + DiscoveredItem::Function { + final_name: canonical_name.clone(), + } + }); + + let link_name_attr = self.link_name().or_else(|| { + let mangled_name = mangled_name.unwrap_or(name); + (!utils::names_will_be_identical_after_mangling( + &canonical_name, + mangled_name, + Some(abi), + )) + .then_some(mangled_name) + }); + + if let Some(link_name) = link_name_attr { + if !is_dynamic_function { + attributes.push(attributes::link_name::(link_name)); + } + } + + let mut block_attributes = quote! {}; + for attr in &ctx.options().extern_fn_block_attrs { + let parsed_attr = proc_macro2::TokenStream::from_str(attr).unwrap_or_else( + |err| { + panic!( + "Error parsing extern fn block attribute `{attr}`: {err}" + ) + }, + ); + block_attributes.extend(quote! { + #parsed_attr + }); + } + + let should_wrap = is_internal && + ctx.options().wrap_static_fns && + link_name_attr.is_none(); + + if should_wrap { + let name = canonical_name.clone() + ctx.wrap_static_fns_suffix(); + attributes.push(attributes::link_name::(&name)); + } + + let wrap_as_variadic = if should_wrap && !signature.is_variadic() { + utils::wrap_as_variadic_fn(ctx, signature, name) + } else { + None + }; + + let (ident, args) = if let Some(WrapAsVariadic { + idx_of_va_list_arg, + new_name, + }) = &wrap_as_variadic + { + ( + new_name, + utils::fnsig_arguments_iter( + ctx, + // Prune argument at index (idx_of_va_list_arg) + signature.argument_types().iter().enumerate().filter_map( + |(idx, t)| { + if idx == *idx_of_va_list_arg { + None + } else { + Some(t) + } + }, + ), + // and replace it by a `...` (variadic symbol and the end of the signature) + true, + ), + ) + } else { + (&canonical_name, utils::fnsig_arguments(ctx, signature)) + }; + let ret = utils::fnsig_return_ty(ctx, signature); + + let ident = ctx.rust_ident(ident); + + let safety = ctx + .options() + .rust_features + .unsafe_extern_blocks + .then(|| quote!(unsafe)); + + let tokens = quote! { + #block_attributes + #safety extern #abi { + #(#attributes)* + pub fn #ident ( #( #args ),* ) #ret; + } + }; + + // Add the item to the serialization list if necessary + if should_wrap { + result + .items_to_serialize + .push((item.id(), wrap_as_variadic)); + } + + // If we're doing dynamic binding generation, add to the dynamic items. + if is_dynamic_function { + let ident_str = ident.to_string(); + let symbol = link_name_attr.unwrap_or(&ident_str); + let args_identifiers = + utils::fnsig_argument_identifiers(ctx, signature); + let ret_ty = utils::fnsig_return_ty(ctx, signature); + result.dynamic_items().push_func( + &ident, + symbol, + abi, + signature.is_variadic(), + ctx.options().dynamic_link_require_all, + &args, + &args_identifiers, + &ret, + &ret_ty, + &attributes, + ctx, + ); + } else { + result.push(tokens); + } + Some(times_seen) + } +} + +#[cfg_attr(not(feature = "experimental"), allow(unused_variables))] +fn unsupported_abi_diagnostic( + fn_name: &str, + variadic: bool, + location: Option<&crate::clang::SourceLocation>, + ctx: &BindgenContext, + error: &Error, +) { + warn!( + "Skipping {}function `{fn_name}` because the {error}", + if variadic { "variadic " } else { "" }, + ); + + #[cfg(feature = "experimental")] + if ctx.options().emit_diagnostics { + use crate::diagnostics::{get_line, Diagnostic, Level, Slice}; + + let mut diag = Diagnostic::default(); + diag.with_title( + format!( + "Skipping {}function `{fn_name}` because the {error}", + if variadic { "variadic " } else { "" }, + ), + Level::Warning, + ) + .add_annotation( + "No code will be generated for this function.", + Level::Warning, + ) + .add_annotation( + format!( + "The configured Rust version is {}.", + ctx.options().rust_target + ), + Level::Note, + ); + + if let Some(loc) = location { + let (file, line, col, _) = loc.location(); + + if let Some(filename) = file.name() { + if let Ok(Some(source)) = get_line(&filename, line) { + let mut slice = Slice::default(); + slice + .with_source(source) + .with_location(filename, line, col); + diag.add_slice(slice); + } + } + } + + diag.display(); + } +} + +fn variadic_fn_diagnostic( + fn_name: &str, + _location: Option<&crate::clang::SourceLocation>, + _ctx: &BindgenContext, +) { + warn!( + "Cannot generate wrapper for the static variadic function `{fn_name}`." + ); + + #[cfg(feature = "experimental")] + if _ctx.options().emit_diagnostics { + use crate::diagnostics::{get_line, Diagnostic, Level, Slice}; + + let mut diag = Diagnostic::default(); + + diag.with_title(format!("Cannot generate wrapper for the static function `{fn_name}`."), Level::Warning) + .add_annotation("The `--wrap-static-fns` feature does not support variadic functions.", Level::Note) + .add_annotation("No code will be generated for this function.", Level::Note); + + if let Some(loc) = _location { + let (file, line, col, _) = loc.location(); + + if let Some(filename) = file.name() { + if let Ok(Some(source)) = get_line(&filename, line) { + let mut slice = Slice::default(); + slice + .with_source(source) + .with_location(filename, line, col); + diag.add_slice(slice); + } + } + } + + diag.display(); + } +} + +fn objc_method_codegen( + ctx: &BindgenContext, + method: &ObjCMethod, + methods: &mut Vec, + class_name: Option<&str>, + rust_class_name: &str, + prefix: &str, +) { + // This would ideally resolve the method into an Item, and use + // Item::process_before_codegen; however, ObjC methods are not currently + // made into function items. + let name = format!("{rust_class_name}::{prefix}{}", method.rust_name()); + if ctx.options().blocklisted_items.matches(name) { + return; + } + + let signature = method.signature(); + let fn_args = utils::fnsig_arguments(ctx, signature); + let fn_ret = utils::fnsig_return_ty(ctx, signature); + + let sig = if method.is_class_method() { + quote! { + ( #( #fn_args ),* ) #fn_ret + } + } else { + let self_arr = [quote! { &self }]; + let args = self_arr.iter().chain(fn_args.iter()); + quote! { + ( #( #args ),* ) #fn_ret + } + }; + + let methods_and_args = method.format_method_call(&fn_args); + + let body = { + let body = if method.is_class_method() { + let class_name = ctx.rust_ident( + class_name + .expect("Generating a class method without class name?"), + ); + quote!(msg_send!(class!(#class_name), #methods_and_args)) + } else { + quote!(msg_send!(*self, #methods_and_args)) + }; + + ctx.wrap_unsafe_ops(body) + }; + + let method_name = ctx.rust_ident(format!("{prefix}{}", method.rust_name())); + + methods.push(quote! { + unsafe fn #method_name #sig where ::Target: objc::Message + Sized { + #body + } + }); +} + +impl CodeGenerator for ObjCInterface { + type Extra = Item; + type Return = (); + + fn codegen( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'_>, + item: &Item, + ) { + debug_assert!(item.is_enabled_for_codegen(ctx)); + + let mut impl_items = vec![]; + let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::"); + + for method in self.methods() { + objc_method_codegen( + ctx, + method, + &mut impl_items, + None, + &rust_class_name, + "", + ); + } + + for class_method in self.class_methods() { + let ambiquity = self + .methods() + .iter() + .map(|m| m.rust_name()) + .any(|x| x == class_method.rust_name()); + let prefix = if ambiquity { "class_" } else { "" }; + objc_method_codegen( + ctx, + class_method, + &mut impl_items, + Some(self.name()), + &rust_class_name, + prefix, + ); + } + + let trait_name = ctx.rust_ident(self.rust_name()); + let trait_constraints = quote! { + Sized + std::ops::Deref + }; + let trait_block = if self.is_template() { + let template_names: Vec = self + .template_names + .iter() + .map(|g| ctx.rust_ident(g)) + .collect(); + + quote! { + pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints { + #( #impl_items )* + } + } + } else { + quote! { + pub trait #trait_name : #trait_constraints { + #( #impl_items )* + } + } + }; + + let class_name = ctx.rust_ident(self.name()); + if !self.is_category() && !self.is_protocol() { + let struct_block = quote! { + #[repr(transparent)] + #[derive(Debug, Copy, Clone)] + pub struct #class_name(pub id); + impl std::ops::Deref for #class_name { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { + &*self.0 + } + } + } + unsafe impl objc::Message for #class_name { } + impl #class_name { + pub fn alloc() -> Self { + Self(unsafe { + msg_send!(class!(#class_name), alloc) + }) + } + } + }; + result.push(struct_block); + let mut protocol_set: HashSet = Default::default(); + for protocol_id in &self.conforms_to { + protocol_set.insert(*protocol_id); + let protocol_name = ctx.rust_ident( + ctx.resolve_type(protocol_id.expect_type_id(ctx)) + .name() + .unwrap(), + ); + let impl_trait = quote! { + impl #protocol_name for #class_name { } + }; + result.push(impl_trait); + } + let mut parent_class = self.parent_class; + while let Some(parent_id) = parent_class { + let parent = parent_id + .expect_type_id(ctx) + .into_resolver() + .through_type_refs() + .resolve(ctx) + .expect_type() + .kind(); + + let TypeKind::ObjCInterface(parent) = parent else { + break; + }; + parent_class = parent.parent_class; + + let parent_name = ctx.rust_ident(parent.rust_name()); + let impl_trait = if parent.is_template() { + let template_names: Vec = parent + .template_names + .iter() + .map(|g| ctx.rust_ident(g)) + .collect(); + quote! { + impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name { + } + } + } else { + quote! { + impl #parent_name for #class_name { } + } + }; + result.push(impl_trait); + for protocol_id in &parent.conforms_to { + if protocol_set.insert(*protocol_id) { + let protocol_name = ctx.rust_ident( + ctx.resolve_type(protocol_id.expect_type_id(ctx)) + .name() + .unwrap(), + ); + let impl_trait = quote! { + impl #protocol_name for #class_name { } + }; + result.push(impl_trait); + } + } + if !parent.is_template() { + let parent_struct_name = parent.name(); + let child_struct_name = self.name(); + let parent_struct = ctx.rust_ident(parent_struct_name); + let from_block = quote! { + impl From<#class_name> for #parent_struct { + fn from(child: #class_name) -> #parent_struct { + #parent_struct(child.0) + } + } + }; + result.push(from_block); + + let error_msg = format!( + "This {parent_struct_name} cannot be downcasted to {child_struct_name}" + ); + let try_into_block = quote! { + impl std::convert::TryFrom<#parent_struct> for #class_name { + type Error = &'static str; + fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> { + let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))}; + if is_kind_of { + Ok(#class_name(parent.0)) + } else { + Err(#error_msg) + } + } + } + }; + result.push(try_into_block); + } + } + } + + if !self.is_protocol() { + let impl_block = if self.is_template() { + let template_names: Vec = self + .template_names + .iter() + .map(|g| ctx.rust_ident(g)) + .collect(); + quote! { + impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name { + } + } + } else { + quote! { + impl #trait_name for #class_name { + } + } + }; + result.push(impl_block); + } + + result.push(trait_block); + result.saw_objc(); + } +} + +pub(crate) fn codegen( + context: BindgenContext, +) -> Result<(proc_macro2::TokenStream, BindgenOptions), CodegenError> { + context.gen(|context| { + let _t = context.timer("codegen"); + let counter = Cell::new(0); + let mut result = CodegenResult::new(&counter); + + debug!("codegen: {:?}", context.options()); + + if context.options().emit_ir { + let codegen_items = context.codegen_items(); + for (id, item) in context.items() { + if codegen_items.contains(&id) { + println!("ir: {id:?} = {item:#?}"); + } + } + } + + if let Some(path) = context.options().emit_ir_graphviz.as_ref() { + match dot::write_dot_file(context, path) { + Ok(()) => info!( + "Your dot file was generated successfully into: {path}" + ), + Err(e) => warn!("{e}"), + } + } + + if let Some(spec) = context.options().depfile.as_ref() { + match spec.write(context.deps()) { + Ok(()) => info!( + "Your depfile was generated successfully into: {}", + spec.depfile_path.display() + ), + Err(e) => warn!("{e}"), + } + } + + context.resolve_item(context.root_module()).codegen( + context, + &mut result, + &(), + ); + + if let Some(ref lib_name) = context.options().dynamic_library_name { + let lib_ident = context.rust_ident(lib_name); + let dynamic_items_tokens = + result.dynamic_items().get_tokens(&lib_ident, context); + result.push(dynamic_items_tokens); + } + + utils::serialize_items(&result, context)?; + + Ok(postprocessing::postprocessing( + result.items, + context.options(), + )) + }) +} + +pub(crate) mod utils { + use super::helpers::BITFIELD_UNIT; + use super::serialize::CSerialize; + use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque}; + use crate::callbacks::DiscoveredItemId; + use crate::ir::context::BindgenContext; + use crate::ir::context::TypeId; + use crate::ir::function::{Abi, ClangAbi, FunctionSig}; + use crate::ir::item::{Item, ItemCanonicalPath}; + use crate::ir::ty::TypeKind; + use crate::{args_are_cpp, file_is_cpp}; + use std::borrow::Cow; + use std::io::Write; + use std::mem; + use std::path::PathBuf; + use std::str::FromStr; + + pub(super) fn serialize_items( + result: &CodegenResult, + context: &BindgenContext, + ) -> Result<(), CodegenError> { + if result.items_to_serialize.is_empty() { + return Ok(()); + } + + let path = context.options().wrap_static_fns_path.as_ref().map_or_else( + || std::env::temp_dir().join("bindgen").join("extern"), + PathBuf::from, + ); + + let dir = path.parent().unwrap(); + + if !dir.exists() { + std::fs::create_dir_all(dir)?; + } + + let is_cpp = args_are_cpp(&context.options().clang_args) || + context + .options() + .input_headers + .iter() + .any(|h| file_is_cpp(h)); + + let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" }); + + let mut code = Vec::new(); + + if !context.options().input_headers.is_empty() { + for header in &context.options().input_headers { + writeln!(code, "#include \"{header}\"")?; + } + + writeln!(code)?; + } + + if !context.options().input_header_contents.is_empty() { + for (name, contents) in &context.options().input_header_contents { + writeln!(code, "// {name}\n{contents}")?; + } + + writeln!(code)?; + } + + writeln!(code, "// Static wrappers\n")?; + + for (id, wrap_as_variadic) in &result.items_to_serialize { + let item = context.resolve_item(*id); + item.serialize(context, wrap_as_variadic, &mut vec![], &mut code)?; + } + + std::fs::write(source_path, code)?; + + Ok(()) + } + + pub(super) fn wrap_as_variadic_fn( + ctx: &BindgenContext, + signature: &FunctionSig, + name: &str, + ) -> Option { + // Fast path, exclude because: + // - with 0 args: no va_list possible, so no point searching for one + // - with 1 args: cannot have a `va_list` and another arg (required by va_start) + if signature.argument_types().len() <= 1 { + return None; + } + + let mut it = signature.argument_types().iter().enumerate().filter_map( + |(idx, (_name, mut type_id))| { + // Hand rolled visitor that checks for the presence of `va_list` + loop { + let ty = ctx.resolve_type(type_id); + if Some("__builtin_va_list") == ty.name() { + return Some(idx); + } + match ty.kind() { + TypeKind::Alias(type_id_alias) => { + type_id = *type_id_alias; + } + TypeKind::ResolvedTypeRef(type_id_typedef) => { + type_id = *type_id_typedef; + } + _ => break, + } + } + None + }, + ); + + // Return THE idx (by checking that there is no idx after) + // This is done since we cannot handle multiple `va_list` + it.next().filter(|_| it.next().is_none()).and_then(|idx| { + // Call the `wrap_as_variadic_fn` callback + #[cfg(feature = "experimental")] + { + ctx.options() + .last_callback(|c| c.wrap_as_variadic_fn(name)) + .map(|new_name| super::WrapAsVariadic { + new_name, + idx_of_va_list_arg: idx, + }) + } + #[cfg(not(feature = "experimental"))] + { + let _ = name; + let _ = idx; + None + } + }) + } + + pub(crate) fn prepend_bitfield_unit_type( + ctx: &BindgenContext, + result: &mut Vec, + ) { + if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) || + ctx.options().blocklisted_types.matches(BITFIELD_UNIT) + { + return; + } + + let bitfield_unit_src = include_str!("./bitfield_unit.rs"); + let bitfield_unit_src = if true { + Cow::Borrowed(bitfield_unit_src) + } else { + Cow::Owned(bitfield_unit_src.replace("const fn ", "fn ")) + }; + let bitfield_unit_type = + proc_macro2::TokenStream::from_str(&bitfield_unit_src).unwrap(); + let bitfield_unit_type = quote!(#bitfield_unit_type); + + let items = vec![bitfield_unit_type]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_objc_header( + ctx: &BindgenContext, + result: &mut Vec, + ) { + let use_objc = if ctx.options().objc_extern_crate { + quote! { + #[macro_use] + extern crate objc; + } + } else { + quote! { + use objc::{self, msg_send, sel, sel_impl, class}; + } + }; + + let id_type = quote! { + #[allow(non_camel_case_types)] + pub type id = *mut objc::runtime::Object; + }; + + let items = vec![use_objc, id_type]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_block_header( + ctx: &BindgenContext, + result: &mut Vec, + ) { + let use_block = if ctx.options().block_extern_crate { + quote! { + extern crate block; + } + } else { + quote! { + use block; + } + }; + + let items = vec![use_block]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_union_types( + ctx: &BindgenContext, + result: &mut Vec, + ) { + let prefix = ctx.trait_prefix(); + + // If the target supports `const fn`, declare eligible functions + // as `const fn` else just `fn`. + let const_fn = if true { + quote! { const fn } + } else { + quote! { fn } + }; + + // TODO(emilio): The fmt::Debug impl could be way nicer with + // std::intrinsics::type_name, but... + let union_field_decl = quote! { + #[repr(C)] + pub struct __BindgenUnionField(::#prefix::marker::PhantomData); + }; + + let transmute = + ctx.wrap_unsafe_ops(quote!(::#prefix::mem::transmute(self))); + + let union_field_impl = quote! { + impl __BindgenUnionField { + #[inline] + pub #const_fn new() -> Self { + __BindgenUnionField(::#prefix::marker::PhantomData) + } + + #[inline] + pub unsafe fn as_ref(&self) -> &T { + #transmute + } + + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + #transmute + } + } + }; + + let union_field_default_impl = quote! { + impl ::#prefix::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } + } + }; + + let union_field_clone_impl = quote! { + impl ::#prefix::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } + } + }; + + let union_field_copy_impl = quote! { + impl ::#prefix::marker::Copy for __BindgenUnionField {} + }; + + let union_field_debug_impl = quote! { + impl ::#prefix::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>) + -> ::#prefix::fmt::Result { + fmt.write_str("__BindgenUnionField") + } + } + }; + + // The actual memory of the filed will be hashed, so that's why these + // field doesn't do anything with the hash. + let union_field_hash_impl = quote! { + impl ::#prefix::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) { + } + } + }; + + let union_field_partialeq_impl = quote! { + impl ::#prefix::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } + } + }; + + let union_field_eq_impl = quote! { + impl ::#prefix::cmp::Eq for __BindgenUnionField { + } + }; + + let items = vec![ + union_field_decl, + union_field_impl, + union_field_default_impl, + union_field_clone_impl, + union_field_copy_impl, + union_field_debug_impl, + union_field_hash_impl, + union_field_partialeq_impl, + union_field_eq_impl, + ]; + + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_incomplete_array_types( + ctx: &BindgenContext, + result: &mut Vec, + ) { + let prefix = ctx.trait_prefix(); + + // If the target supports `const fn`, declare eligible functions + // as `const fn` else just `fn`. + let const_fn = if true { + quote! { const fn } + } else { + quote! { fn } + }; + + let incomplete_array_decl = quote! { + #[repr(C)] + #[derive(Default)] + pub struct __IncompleteArrayField( + ::#prefix::marker::PhantomData, [T; 0]); + }; + + let from_raw_parts = ctx.wrap_unsafe_ops(quote! ( + ::#prefix::slice::from_raw_parts(self.as_ptr(), len) + )); + let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! ( + ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + )); + + let incomplete_array_impl = quote! { + impl __IncompleteArrayField { + #[inline] + pub #const_fn new() -> Self { + __IncompleteArrayField(::#prefix::marker::PhantomData, []) + } + + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + #from_raw_parts + } + + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + #from_raw_parts_mut + } + } + }; + + let incomplete_array_debug_impl = quote! { + impl ::#prefix::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>) + -> ::#prefix::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } + } + }; + + let items = vec![ + incomplete_array_decl, + incomplete_array_impl, + incomplete_array_debug_impl, + ]; + + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_float16_type( + result: &mut Vec, + ) { + let float16_type = quote! { + #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] + #[repr(transparent)] + pub struct __BindgenFloat16(pub u16); + }; + + let items = vec![float16_type]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_complex_type( + result: &mut Vec, + ) { + let complex_type = quote! { + #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] + #[repr(C)] + pub struct __BindgenComplex { + pub re: T, + pub im: T + } + }; + + let items = vec![complex_type]; + let old_items = mem::replace(result, items); + result.extend(old_items); + } + + pub(crate) fn prepend_opaque_array_types( + ctx: &BindgenContext, + result: &mut Vec, + ) { + let mut tys = vec![]; + // If Bindgen could only determine the size and alignment of a type, it is represented like + // this. + for align in ctx.opaque_array_types_needed() { + let ident = if align == 1 { + format_ident!("__BindgenOpaqueArray") + } else { + format_ident!("__BindgenOpaqueArray{align}") + }; + let repr = if align <= 1 { + quote! { #[repr(C)] } + } else { + let explicit = super::helpers::ast_ty::int_expr(align as i64); + quote! { #[repr(C, align(#explicit))] } + }; + tys.push(quote! { + #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] + #repr + pub struct #ident(pub T); + impl Default for #ident<[T; N]> { + fn default() -> Self { + Self([::default(); N]) + } + } + }); + } + result.splice(0..0, tys); + } + + pub(crate) fn build_path( + item: &Item, + ctx: &BindgenContext, + ) -> error::Result { + let path = item.namespace_aware_canonical_path(ctx); + let tokens = + proc_macro2::TokenStream::from_str(&path.join("::")).unwrap(); + + Ok(syn::parse_quote! { #tokens }) + } + + fn primitive_ty(ctx: &BindgenContext, name: &str) -> syn::Type { + let ident = ctx.rust_ident_raw(name); + syn::parse_quote! { #ident } + } + + pub(crate) fn type_from_named( + ctx: &BindgenContext, + name: &str, + ) -> Option { + // FIXME: We could use the inner item to check this is really a + // primitive type but, who the heck overrides these anyway? + Some(match name { + "int8_t" => primitive_ty(ctx, "i8"), + "uint8_t" => primitive_ty(ctx, "u8"), + "int16_t" => primitive_ty(ctx, "i16"), + "uint16_t" => primitive_ty(ctx, "u16"), + "int32_t" => primitive_ty(ctx, "i32"), + "uint32_t" => primitive_ty(ctx, "u32"), + "int64_t" => primitive_ty(ctx, "i64"), + "uint64_t" => primitive_ty(ctx, "u64"), + + "size_t" if ctx.options().size_t_is_usize => { + primitive_ty(ctx, "usize") + } + "uintptr_t" => primitive_ty(ctx, "usize"), + + "ssize_t" if ctx.options().size_t_is_usize => { + primitive_ty(ctx, "isize") + } + "intptr_t" | "ptrdiff_t" => primitive_ty(ctx, "isize"), + _ => return None, + }) + } + + fn fnsig_return_ty_internal( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> syn::Type { + if sig.is_divergent() { + return syn::parse_quote! { ! }; + } + + let canonical_type_kind = sig + .return_type() + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(ctx) + .kind() + .expect_type() + .kind(); + + match canonical_type_kind { + TypeKind::Void => syn::parse_quote! { () }, + _ => sig.return_type().to_rust_ty_or_opaque(ctx, &()), + } + } + + pub(crate) fn fnsig_return_ty( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> proc_macro2::TokenStream { + match fnsig_return_ty_internal(ctx, sig) { + syn::Type::Tuple(syn::TypeTuple { elems, .. }) + if elems.is_empty() => + { + quote! {} + } + ty => quote! { -> #ty }, + } + } + + pub(crate) fn fnsig_argument_type( + ctx: &BindgenContext, + ty: TypeId, + ) -> syn::Type { + use super::ToPtr; + + let arg_item = ctx.resolve_item(ty); + let arg_ty = arg_item.kind().expect_type(); + + // From the C90 standard[1]: + // + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + // + // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html + match *arg_ty.canonical_type(ctx).kind() { + TypeKind::Array(t, _) => { + let stream = if ctx.options().array_pointers_in_arguments { + arg_ty.to_rust_ty_or_opaque(ctx, arg_item) + } else { + t.to_rust_ty_or_opaque(ctx, &()) + }; + stream + .to_ptr(ctx.resolve_type(t).is_const() || arg_ty.is_const()) + } + TypeKind::Pointer(inner) => { + let inner = ctx.resolve_item(inner); + let inner_ty = inner.expect_type(); + if let TypeKind::ObjCInterface(ref interface) = + *inner_ty.canonical_type(ctx).kind() + { + let name = ctx.rust_ident(interface.name()); + syn::parse_quote! { #name } + } else { + arg_item.to_rust_ty_or_opaque(ctx, &()) + } + } + _ => arg_item.to_rust_ty_or_opaque(ctx, &()), + } + } + + pub(crate) fn fnsig_arguments_iter< + 'a, + I: Iterator, TypeId)>, + >( + ctx: &BindgenContext, + args_iter: I, + is_variadic: bool, + ) -> Vec { + let mut unnamed_arguments = 0; + let mut args = args_iter + .map(|(name, ty)| { + let arg_ty = fnsig_argument_type(ctx, *ty); + + let arg_name = if let Some(ref name) = *name { + ctx.rust_mangle(name).into_owned() + } else { + unnamed_arguments += 1; + format!("arg{unnamed_arguments}") + }; + + assert!(!arg_name.is_empty()); + let arg_name = ctx.rust_ident(arg_name); + + quote! { + #arg_name : #arg_ty + } + }) + .collect::>(); + + if is_variadic { + args.push(quote! { ... }); + } + + args + } + + pub(crate) fn fnsig_arguments( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> Vec { + fnsig_arguments_iter( + ctx, + sig.argument_types().iter(), + sig.is_variadic(), + ) + } + + pub(crate) fn fnsig_argument_identifiers( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> Vec { + let mut unnamed_arguments = 0; + let args = sig + .argument_types() + .iter() + .map(|&(ref name, _ty)| { + let arg_name = if let Some(ref name) = *name { + ctx.rust_mangle(name).into_owned() + } else { + unnamed_arguments += 1; + format!("arg{unnamed_arguments}") + }; + + assert!(!arg_name.is_empty()); + let arg_name = ctx.rust_ident(arg_name); + + quote! { + #arg_name + } + }) + .collect::>(); + + args + } + + pub(crate) fn fnsig_block( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> proc_macro2::TokenStream { + let args = sig.argument_types().iter().map(|&(_, ty)| { + let arg_item = ctx.resolve_item(ty); + + arg_item.to_rust_ty_or_opaque(ctx, &()) + }); + + let ret_ty = fnsig_return_ty_internal(ctx, sig); + quote! { + *const ::block::Block<(#(#args,)*), #ret_ty> + } + } + + // Returns true if `canonical_name` will end up as `mangled_name` at the + // machine code level, i.e. after LLVM has applied any target specific + // mangling. + pub(crate) fn names_will_be_identical_after_mangling( + canonical_name: &str, + mangled_name: &str, + call_conv: Option, + ) -> bool { + // If the mangled name and the canonical name are the same then no + // mangling can have happened between the two versions. + if canonical_name == mangled_name { + return true; + } + + // Working with &[u8] makes indexing simpler than with &str + let canonical_name = canonical_name.as_bytes(); + let mangled_name = mangled_name.as_bytes(); + + let (mangling_prefix, expect_suffix) = match call_conv { + Some(ClangAbi::Known(Abi::C | Abi::CUnwind)) | + // None is the case for global variables + None => { + (b'_', false) + } + Some(ClangAbi::Known(Abi::Stdcall)) => (b'_', true), + Some(ClangAbi::Known(Abi::Fastcall)) => (b'@', true), + + // This is something we don't recognize, stay on the safe side + // by emitting the `#[link_name]` attribute + Some(_) => return false, + }; + + // Check that the mangled name is long enough to at least contain the + // canonical name plus the expected prefix. + if mangled_name.len() < canonical_name.len() + 1 { + return false; + } + + // Return if the mangled name does not start with the prefix expected + // for the given calling convention. + if mangled_name[0] != mangling_prefix { + return false; + } + + // Check that the mangled name contains the canonical name after the + // prefix + if &mangled_name[1..=canonical_name.len()] != canonical_name { + return false; + } + + // If the given calling convention also prescribes a suffix, check that + // it exists too + if expect_suffix { + let suffix = &mangled_name[canonical_name.len() + 1..]; + + // The shortest suffix is "@0" + if suffix.len() < 2 { + return false; + } + + // Check that the suffix starts with '@' and is all ASCII decimals + // after that. + if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit) + { + return false; + } + } else if mangled_name.len() != canonical_name.len() + 1 { + // If we don't expect a prefix but there is one, we need the + // #[link_name] attribute + return false; + } + + true + } + + pub(super) fn call_discovered_item_callback( + ctx: &BindgenContext, + item: &Item, + discovered_item_creator: impl Fn() -> crate::callbacks::DiscoveredItem, + ) { + let source_location = item.location().map(|clang_location| { + let (file, line, col, byte_offset) = clang_location.location(); + let file_name = file.name(); + crate::callbacks::SourceLocation { + line, + col, + byte_offset, + file_name, + } + }); + ctx.options().for_each_callback(|cb| { + cb.new_item_found( + DiscoveredItemId::new(item.id().as_usize()), + discovered_item_creator(), + source_location.as_ref(), + ); + }); + } +} diff --git a/bindgen/codegen/postprocessing/merge_extern_blocks.rs b/bindgen/codegen/postprocessing/merge_extern_blocks.rs new file mode 100644 index 0000000000..e0f6a34baa --- /dev/null +++ b/bindgen/codegen/postprocessing/merge_extern_blocks.rs @@ -0,0 +1,72 @@ +use syn::{ + visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut}, + File, Item, ItemForeignMod, ItemMod, +}; + +pub(super) fn merge_extern_blocks(file: &mut File) { + Visitor.visit_file_mut(file); +} + +struct Visitor; + +impl VisitMut for Visitor { + fn visit_file_mut(&mut self, file: &mut File) { + visit_items(&mut file.items); + visit_file_mut(self, file); + } + + fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) { + if let Some((_, ref mut items)) = item_mod.content { + visit_items(items); + } + visit_item_mod_mut(self, item_mod); + } +} + +fn visit_items(items: &mut Vec) { + // Keep all the extern blocks in a different `Vec` for faster search. + let mut extern_blocks = Vec::::new(); + + for item in std::mem::take(items) { + if let Item::ForeignMod(ItemForeignMod { + attrs, + abi, + brace_token, + unsafety, + items: extern_block_items, + }) = item + { + let mut exists = false; + for extern_block in &mut extern_blocks { + // Check if there is a extern block with the same ABI and + // attributes. + if extern_block.attrs == attrs && extern_block.abi == abi { + // Merge the items of the two blocks. + extern_block.items.extend_from_slice(&extern_block_items); + exists = true; + break; + } + } + // If no existing extern block had the same ABI and attributes, store + // it. + if !exists { + extern_blocks.push(ItemForeignMod { + attrs, + abi, + brace_token, + unsafety, + items: extern_block_items, + }); + } + } else { + // If the item is not an extern block, we don't have to do anything and just + // push it back. + items.push(item); + } + } + + // Move all the extern blocks alongside the rest of the items. + for extern_block in extern_blocks { + items.push(Item::ForeignMod(extern_block)); + } +} diff --git a/bindgen/codegen/postprocessing/mod.rs b/bindgen/codegen/postprocessing/mod.rs new file mode 100644 index 0000000000..9641698521 --- /dev/null +++ b/bindgen/codegen/postprocessing/mod.rs @@ -0,0 +1,57 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{parse2, File}; + +use crate::BindgenOptions; + +mod merge_extern_blocks; +mod sort_semantically; + +use merge_extern_blocks::merge_extern_blocks; +use sort_semantically::sort_semantically; + +struct PostProcessingPass { + should_run: fn(&BindgenOptions) -> bool, + run: fn(&mut File), +} + +// TODO: This can be a const fn when mutable references are allowed in const +// context. +macro_rules! pass { + ($pass:ident) => { + PostProcessingPass { + should_run: |options| options.$pass, + run: |file| $pass(file), + } + }; +} + +const PASSES: &[PostProcessingPass] = + &[pass!(merge_extern_blocks), pass!(sort_semantically)]; + +pub(crate) fn postprocessing( + items: Vec, + options: &BindgenOptions, +) -> TokenStream { + let items = items.into_iter().collect(); + let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options)); + + if !require_syn { + return items; + } + + // This syn business is a hack, for now. This means that we are re-parsing already + // generated code using `syn` (as opposed to `quote`) because `syn` provides us more + // control over the elements. + // The `unwrap` here is deliberate because bindgen should generate valid rust items at all + // times. + let mut file = parse2::(items).unwrap(); + + for pass in PASSES { + if (pass.should_run)(options) { + (pass.run)(&mut file); + } + } + + file.into_token_stream() +} diff --git a/bindgen/codegen/postprocessing/sort_semantically.rs b/bindgen/codegen/postprocessing/sort_semantically.rs new file mode 100644 index 0000000000..e9bb5dc308 --- /dev/null +++ b/bindgen/codegen/postprocessing/sort_semantically.rs @@ -0,0 +1,46 @@ +use syn::{ + visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut}, + File, Item, ItemMod, +}; + +pub(super) fn sort_semantically(file: &mut File) { + Visitor.visit_file_mut(file); +} + +struct Visitor; + +impl VisitMut for Visitor { + fn visit_file_mut(&mut self, file: &mut File) { + visit_items(&mut file.items); + visit_file_mut(self, file); + } + + fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) { + if let Some((_, ref mut items)) = item_mod.content { + visit_items(items); + } + visit_item_mod_mut(self, item_mod); + } +} + +fn visit_items(items: &mut [Item]) { + items.sort_by_key(|item| match item { + Item::Type(_) => 0, + Item::Struct(_) => 1, + Item::Const(_) => 2, + Item::Fn(_) => 3, + Item::Enum(_) => 4, + Item::Union(_) => 5, + Item::Static(_) => 6, + Item::Trait(_) => 7, + Item::TraitAlias(_) => 8, + Item::Impl(_) => 9, + Item::Mod(_) => 10, + Item::Use(_) => 11, + Item::Verbatim(_) => 12, + Item::ExternCrate(_) => 13, + Item::ForeignMod(_) => 14, + Item::Macro(_) => 15, + _ => 18, + }); +} diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs new file mode 100644 index 0000000000..9af48aa8ff --- /dev/null +++ b/bindgen/codegen/serialize.rs @@ -0,0 +1,443 @@ +use std::io::Write; + +use crate::callbacks::IntKind; + +use crate::ir::comp::CompKind; +use crate::ir::context::{BindgenContext, TypeId}; +use crate::ir::function::{Function, FunctionKind}; +use crate::ir::item::Item; +use crate::ir::item::ItemCanonicalName; +use crate::ir::item_kind::ItemKind; +use crate::ir::ty::{FloatKind, Type, TypeKind}; + +use super::{CodegenError, WrapAsVariadic}; + +fn get_loc(item: &Item) -> String { + item.location() + .map_or_else(|| "unknown".to_owned(), |x| x.to_string()) +} + +pub(super) trait CSerialize<'a> { + type Extra; + + fn serialize( + &self, + ctx: &BindgenContext, + extra: Self::Extra, + stack: &mut Vec, + writer: &mut W, + ) -> Result<(), CodegenError>; +} + +impl<'a> CSerialize<'a> for Item { + type Extra = &'a Option; + + fn serialize( + &self, + ctx: &BindgenContext, + extra: Self::Extra, + stack: &mut Vec, + writer: &mut W, + ) -> Result<(), CodegenError> { + match self.kind() { + ItemKind::Function(func) => { + func.serialize(ctx, (self, extra), stack, writer) + } + kind => Err(CodegenError::Serialize { + msg: format!("Cannot serialize item kind {kind:?}"), + loc: get_loc(self), + }), + } + } +} + +impl<'a> CSerialize<'a> for Function { + type Extra = (&'a Item, &'a Option); + + fn serialize( + &self, + ctx: &BindgenContext, + (item, wrap_as_variadic): Self::Extra, + stack: &mut Vec, + writer: &mut W, + ) -> Result<(), CodegenError> { + if self.kind() != FunctionKind::Function { + return Err(CodegenError::Serialize { + msg: format!( + "Cannot serialize function kind {:?}", + self.kind(), + ), + loc: get_loc(item), + }); + } + + let TypeKind::Function(signature) = + ctx.resolve_type(self.signature()).kind() + else { + unreachable!() + }; + + assert!(!signature.is_variadic()); + + let name = self.name(); + + // Function arguments stored as `(name, type_id)` tuples. + let args = { + let mut count = 0; + + let idx_to_prune = wrap_as_variadic.as_ref().map( + |WrapAsVariadic { + idx_of_va_list_arg, .. + }| *idx_of_va_list_arg, + ); + + signature + .argument_types() + .iter() + .cloned() + .enumerate() + .filter_map(|(idx, (opt_name, type_id))| { + if Some(idx) == idx_to_prune { + None + } else { + Some(( + opt_name.unwrap_or_else(|| { + let name = format!("arg_{count}"); + count += 1; + name + }), + type_id, + )) + } + }) + .collect::>() + }; + + // The name used for the wrapper self. + let wrap_name = format!("{name}{}", ctx.wrap_static_fns_suffix()); + + // The function's return type + let (ret_item, ret_ty) = { + let type_id = signature.return_type(); + let ret_item = ctx.resolve_item(type_id); + let ret_ty = ret_item.expect_type(); + + // Write `ret_ty`. + ret_ty.serialize(ctx, ret_item, stack, writer)?; + + (ret_item, ret_ty) + }; + + const INDENT: &str = " "; + + // Write `wrap_name(args`. + write!(writer, " {wrap_name}(")?; + serialize_args(&args, ctx, writer)?; + + if wrap_as_variadic.is_none() { + // Write `) { name(` if the function returns void and `) { return name(` if it does not. + if ret_ty.is_void() { + write!(writer, ") {{ {name}(")?; + } else { + write!(writer, ") {{ return {name}(")?; + } + } else { + // Write `, ...) {` + writeln!(writer, ", ...) {{")?; + + // Declare the return type `RET_TY ret;` if their is a need to do so + if !ret_ty.is_void() { + write!(writer, "{INDENT}")?; + ret_ty.serialize(ctx, ret_item, stack, writer)?; + writeln!(writer, " ret;")?; + } + + // Setup va_list + writeln!(writer, "{INDENT}va_list ap;\n")?; + writeln!( + writer, + "{INDENT}va_start(ap, {});", + args.last().unwrap().0 + )?; + + write!(writer, "{INDENT}")?; + // Write `ret = name(` or `name(` depending if the function returns something + if !ret_ty.is_void() { + write!(writer, "ret = ")?; + } + write!(writer, "{name}(")?; + } + + // Get the arguments names and insert at the right place if necessary `ap` + let mut args: Vec<_> = args.into_iter().map(|(name, _)| name).collect(); + if let Some(WrapAsVariadic { + idx_of_va_list_arg, .. + }) = wrap_as_variadic + { + args.insert(*idx_of_va_list_arg, "ap".to_owned()); + } + + // Write `arg_names);`. + serialize_sep(", ", args.iter(), ctx, writer, |name, _, buf| { + write!(buf, "{name}").map_err(From::from) + })?; + #[rustfmt::skip] + write!(writer, ");{}", if wrap_as_variadic.is_none() { " " } else { "\n" })?; + + if wrap_as_variadic.is_some() { + // End va_list and return the result if their is one + writeln!(writer, "{INDENT}va_end(ap);")?; + if !ret_ty.is_void() { + writeln!(writer, "{INDENT}return ret;")?; + } + } + + writeln!(writer, "}}")?; + + Ok(()) + } +} + +impl CSerialize<'_> for TypeId { + type Extra = (); + + fn serialize( + &self, + ctx: &BindgenContext, + (): Self::Extra, + stack: &mut Vec, + writer: &mut W, + ) -> Result<(), CodegenError> { + let item = ctx.resolve_item(*self); + item.expect_type().serialize(ctx, item, stack, writer) + } +} + +impl<'a> CSerialize<'a> for Type { + type Extra = &'a Item; + + fn serialize( + &self, + ctx: &BindgenContext, + item: Self::Extra, + stack: &mut Vec, + writer: &mut W, + ) -> Result<(), CodegenError> { + match self.kind() { + TypeKind::Void => { + if self.is_const() { + write!(writer, "const ")?; + } + write!(writer, "void")?; + } + TypeKind::NullPtr => { + if self.is_const() { + write!(writer, "const ")?; + } + write!(writer, "nullptr_t")?; + } + TypeKind::Int(int_kind) => { + if self.is_const() { + write!(writer, "const ")?; + } + match int_kind { + IntKind::Bool => write!(writer, "bool")?, + IntKind::SChar => write!(writer, "signed char")?, + IntKind::UChar => write!(writer, "unsigned char")?, + IntKind::WChar => write!(writer, "wchar_t")?, + IntKind::Short => write!(writer, "short")?, + IntKind::UShort => write!(writer, "unsigned short")?, + IntKind::Int => write!(writer, "int")?, + IntKind::UInt => write!(writer, "unsigned int")?, + IntKind::Long => write!(writer, "long")?, + IntKind::ULong => write!(writer, "unsigned long")?, + IntKind::LongLong => write!(writer, "long long")?, + IntKind::ULongLong => write!(writer, "unsigned long long")?, + IntKind::Char { .. } => write!(writer, "char")?, + int_kind => { + return Err(CodegenError::Serialize { + msg: format!( + "Cannot serialize integer kind {int_kind:?}" + ), + loc: get_loc(item), + }) + } + } + } + TypeKind::Float(float_kind) => { + if self.is_const() { + write!(writer, "const ")?; + } + match float_kind { + FloatKind::Float16 => write!(writer, "_Float16")?, + FloatKind::Float => write!(writer, "float")?, + FloatKind::Double => write!(writer, "double")?, + FloatKind::LongDouble => write!(writer, "long double")?, + FloatKind::Float128 => write!(writer, "__float128")?, + } + } + TypeKind::Complex(float_kind) => { + if self.is_const() { + write!(writer, "const ")?; + } + match float_kind { + FloatKind::Float16 => write!(writer, "_Float16 complex")?, + FloatKind::Float => write!(writer, "float complex")?, + FloatKind::Double => write!(writer, "double complex")?, + FloatKind::LongDouble => { + write!(writer, "long double complex")?; + } + FloatKind::Float128 => write!(writer, "__complex128")?, + } + } + TypeKind::Alias(type_id) => { + if let Some(name) = self.name() { + if self.is_const() { + write!(writer, "const {name}")?; + } else { + write!(writer, "{name}")?; + } + } else { + type_id.serialize(ctx, (), stack, writer)?; + } + } + TypeKind::Array(type_id, length) => { + type_id.serialize(ctx, (), stack, writer)?; + write!(writer, " [{length}]")?; + } + TypeKind::Function(signature) => { + if self.is_const() { + stack.push("const ".to_string()); + } + + signature.return_type().serialize( + ctx, + (), + &mut vec![], + writer, + )?; + + write!(writer, " (")?; + while let Some(item) = stack.pop() { + write!(writer, "{item}")?; + } + write!(writer, ")")?; + + let args = signature.argument_types(); + if args.is_empty() { + write!(writer, " (void)")?; + } else { + write!(writer, " (")?; + serialize_sep( + ", ", + args.iter(), + ctx, + writer, + |(name, type_id), ctx, buf| { + let mut stack = vec![]; + if let Some(name) = name { + stack.push(name.clone()); + } + type_id.serialize(ctx, (), &mut stack, buf) + }, + )?; + write!(writer, ")")?; + } + } + TypeKind::ResolvedTypeRef(type_id) => { + if self.is_const() { + write!(writer, "const ")?; + } + type_id.serialize(ctx, (), stack, writer)?; + } + TypeKind::Pointer(type_id) => { + if self.is_const() { + stack.push("*const ".to_owned()); + } else { + stack.push("*".to_owned()); + } + type_id.serialize(ctx, (), stack, writer)?; + } + TypeKind::Comp(comp_info) => { + if self.is_const() { + write!(writer, "const ")?; + } + + let name = item.canonical_name(ctx); + + match comp_info.kind() { + CompKind::Struct => write!(writer, "struct {name}")?, + CompKind::Union => write!(writer, "union {name}")?, + } + } + TypeKind::Enum(_enum_ty) => { + if self.is_const() { + write!(writer, "const ")?; + } + + let name = item.canonical_name(ctx); + write!(writer, "enum {name}")?; + } + ty => { + return Err(CodegenError::Serialize { + msg: format!("Cannot serialize type kind {ty:?}"), + loc: get_loc(item), + }) + } + } + + if !stack.is_empty() { + write!(writer, " ")?; + while let Some(item) = stack.pop() { + write!(writer, "{item}")?; + } + } + + Ok(()) + } +} + +fn serialize_args( + args: &[(String, TypeId)], + ctx: &BindgenContext, + writer: &mut W, +) -> Result<(), CodegenError> { + if args.is_empty() { + write!(writer, "void")?; + } else { + serialize_sep( + ", ", + args.iter(), + ctx, + writer, + |(name, type_id), ctx, buf| { + type_id.serialize(ctx, (), &mut vec![name.clone()], buf) + }, + )?; + } + + Ok(()) +} + +fn serialize_sep< + W: Write, + F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>, + I: Iterator, +>( + sep: &str, + mut iter: I, + ctx: &BindgenContext, + buf: &mut W, + mut f: F, +) -> Result<(), CodegenError> { + if let Some(item) = iter.next() { + f(item, ctx, buf)?; + let sep = sep.as_bytes(); + for item in iter { + buf.write_all(sep)?; + f(item, ctx, buf)?; + } + } + + Ok(()) +} diff --git a/bindgen/codegen/struct_layout.rs b/bindgen/codegen/struct_layout.rs new file mode 100644 index 0000000000..3dfd076c25 --- /dev/null +++ b/bindgen/codegen/struct_layout.rs @@ -0,0 +1,427 @@ +//! Helpers for code generation that need struct layout + +use super::helpers; + +use crate::ir::comp::CompInfo; +use crate::ir::context::BindgenContext; +use crate::ir::layout::Layout; +use crate::ir::ty::{Type, TypeKind}; +use crate::FieldVisibilityKind; +use proc_macro2::{Ident, Span}; +use std::cmp; + +const MAX_GUARANTEED_ALIGN: usize = 8; + +/// Trace the layout of struct. +#[derive(Debug)] +pub(crate) struct StructLayoutTracker<'a> { + name: &'a str, + ctx: &'a BindgenContext, + comp: &'a CompInfo, + is_packed: bool, + known_type_layout: Option, + is_rust_union: bool, + can_copy_union_fields: bool, + latest_offset: usize, + padding_count: usize, + latest_field_layout: Option, + max_field_align: usize, + last_field_was_bitfield: bool, + visibility: FieldVisibilityKind, + last_field_was_flexible_array: bool, +} + +/// Returns a size aligned to a given value. +pub(crate) fn align_to(size: usize, align: usize) -> usize { + if align == 0 { + return size; + } + + let rem = size % align; + if rem == 0 { + return size; + } + + size + align - rem +} + +#[test] +fn test_align_to() { + assert_eq!(align_to(1, 1), 1); + assert_eq!(align_to(1, 2), 2); + assert_eq!(align_to(1, 4), 4); + assert_eq!(align_to(5, 1), 5); + assert_eq!(align_to(17, 4), 20); +} + +impl<'a> StructLayoutTracker<'a> { + pub(crate) fn new( + ctx: &'a BindgenContext, + comp: &'a CompInfo, + ty: &'a Type, + name: &'a str, + visibility: FieldVisibilityKind, + is_packed: bool, + ) -> Self { + let known_type_layout = ty.layout(ctx); + let (is_rust_union, can_copy_union_fields) = + comp.is_rust_union(ctx, known_type_layout.as_ref(), name); + StructLayoutTracker { + name, + ctx, + comp, + visibility, + is_packed, + known_type_layout, + is_rust_union, + can_copy_union_fields, + latest_offset: 0, + padding_count: 0, + latest_field_layout: None, + max_field_align: 0, + last_field_was_bitfield: false, + last_field_was_flexible_array: false, + } + } + + pub(crate) fn can_copy_union_fields(&self) -> bool { + self.can_copy_union_fields + } + + pub(crate) fn is_rust_union(&self) -> bool { + self.is_rust_union + } + + pub(crate) fn saw_flexible_array(&mut self) { + self.last_field_was_flexible_array = true; + } + + pub(crate) fn saw_vtable(&mut self) { + debug!("saw vtable for {}", self.name); + + let ptr_size = self.ctx.target_pointer_size(); + self.latest_offset += ptr_size; + self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size)); + self.max_field_align = ptr_size; + } + + pub(crate) fn saw_base(&mut self, base_ty: &Type) { + debug!("saw base for {}", self.name); + if let Some(layout) = base_ty.layout(self.ctx) { + self.align_to_latest_field(layout); + + self.latest_offset += self.padding_bytes(layout) + layout.size; + self.latest_field_layout = Some(layout); + self.max_field_align = cmp::max(self.max_field_align, layout.align); + } + } + + pub(crate) fn saw_bitfield_unit(&mut self, layout: Layout) { + debug!("saw bitfield unit for {}: {layout:?}", self.name); + + self.align_to_latest_field(layout); + + self.latest_offset += layout.size; + + debug!( + "Offset: : {} -> {}", + self.latest_offset - layout.size, + self.latest_offset + ); + + self.latest_field_layout = Some(layout); + self.last_field_was_bitfield = true; + self.max_field_align = cmp::max(self.max_field_align, layout.align); + } + + /// Returns a padding field if necessary for a given new field _before_ + /// adding that field. + pub(crate) fn saw_field( + &mut self, + field_name: &str, + field_ty: &Type, + field_offset: Option, + ) -> Option { + let mut field_layout = field_ty.layout(self.ctx)?; + + if let TypeKind::Array(inner, len) = + *field_ty.canonical_type(self.ctx).kind() + { + // FIXME(emilio): As an _ultra_ hack, we correct the layout returned + // by arrays of structs that have a bigger alignment than what we + // can support. + // + // This means that the structs in the array are super-unsafe to + // access, since they won't be properly aligned, but there's not too + // much we can do about it. + if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) + { + if layout.align > MAX_GUARANTEED_ALIGN { + field_layout.size = + align_to(layout.size, layout.align) * len; + field_layout.align = MAX_GUARANTEED_ALIGN; + } + } + } + self.saw_field_with_layout(field_name, field_layout, field_offset) + } + + pub(crate) fn saw_field_with_layout( + &mut self, + field_name: &str, + field_layout: Layout, + field_offset: Option, + ) -> Option { + let will_merge_with_bitfield = self.align_to_latest_field(field_layout); + + let is_union = self.comp.is_union(); + let padding_bytes = match field_offset { + Some(offset) if offset / 8 > self.latest_offset => { + offset / 8 - self.latest_offset + } + _ => { + if will_merge_with_bitfield || + field_layout.align == 0 || + is_union + { + 0 + } else if !self.is_packed { + self.padding_bytes(field_layout) + } else if let Some(mut l) = self.known_type_layout { + if field_layout.align < l.align { + l.align = field_layout.align; + } + self.padding_bytes(l) + } else { + 0 + } + } + }; + + self.latest_offset += padding_bytes; + + let padding_layout = if self.is_packed || is_union { + None + } else { + let force_padding = self.ctx.options().force_explicit_padding; + + // Otherwise the padding is useless. + let need_padding = force_padding || + padding_bytes >= field_layout.align || + field_layout.align > MAX_GUARANTEED_ALIGN; + + debug!( + "Offset: : {} -> {}", + self.latest_offset - padding_bytes, + self.latest_offset + ); + + debug!( + "align field {field_name} to {}/{} with {padding_bytes} padding bytes {field_layout:?}", + self.latest_offset, + field_offset.unwrap_or(0) / 8, + ); + + let padding_align = if force_padding { + 1 + } else { + cmp::min(field_layout.align, MAX_GUARANTEED_ALIGN) + }; + + if need_padding && padding_bytes != 0 { + Some(Layout::new(padding_bytes, padding_align)) + } else { + None + } + }; + + if is_union { + self.latest_offset = + cmp::max(self.latest_offset, field_layout.size); + } else { + self.latest_offset += field_layout.size; + } + self.latest_field_layout = Some(field_layout); + self.max_field_align = + cmp::max(self.max_field_align, field_layout.align); + self.last_field_was_bitfield = false; + + debug!( + "Offset: {field_name}: {} -> {}", + self.latest_offset - field_layout.size, + self.latest_offset + ); + + padding_layout.map(|layout| self.padding_field(layout)) + } + + pub(crate) fn add_tail_padding( + &mut self, + comp_name: &str, + comp_layout: Layout, + ) -> Option { + // Only emit an padding field at the end of a struct if the + // user configures explicit padding. + if !self.ctx.options().force_explicit_padding { + return None; + } + + // Padding doesn't make sense for rust unions. + if self.is_rust_union { + return None; + } + + // Also doesn't make sense for structs with flexible array members + if self.last_field_was_flexible_array { + return None; + } + + if self.latest_offset == comp_layout.size { + // This struct does not contain tail padding. + return None; + } + + trace!( + "need a tail padding field for {comp_name}: offset {} -> size {}", + self.latest_offset, + comp_layout.size + ); + let size = comp_layout.size - self.latest_offset; + Some(self.padding_field(Layout::new(size, 0))) + } + + pub(crate) fn pad_struct( + &mut self, + layout: Layout, + ) -> Option { + debug!("pad_struct:\n\tself = {self:#?}\n\tlayout = {layout:#?}"); + + if layout.size < self.latest_offset { + warn!( + "Calculated wrong layout for {}, too more {} bytes", + self.name, + self.latest_offset - layout.size + ); + return None; + } + + let padding_bytes = layout.size - self.latest_offset; + if padding_bytes == 0 { + return None; + } + + let repr_align = true; + + // We always pad to get to the correct size if the struct is one of + // those we can't align properly. + // + // Note that if the last field we saw was a bitfield, we may need to pad + // regardless, because bitfields don't respect alignment as strictly as + // other fields. + if padding_bytes >= layout.align || + (self.last_field_was_bitfield && + padding_bytes >= self.latest_field_layout.unwrap().align) || + (!repr_align && layout.align > MAX_GUARANTEED_ALIGN) + { + let layout = if self.is_packed { + Layout::new(padding_bytes, 1) + } else if self.last_field_was_bitfield || + layout.align > MAX_GUARANTEED_ALIGN + { + // We've already given up on alignment here. + Layout::for_size(self.ctx, padding_bytes) + } else { + Layout::new(padding_bytes, layout.align) + }; + + debug!("pad bytes to struct {}, {layout:?}", self.name); + + Some(self.padding_field(layout)) + } else { + None + } + } + + pub(crate) fn requires_explicit_align(&self, layout: Layout) -> bool { + let repr_align = true; + + // Always force explicit repr(align) for stuff more than 16-byte aligned + // to work-around https://github.com/rust-lang/rust/issues/54341. + // + // Worst-case this just generates redundant alignment attributes. + if repr_align && self.max_field_align >= 16 { + return true; + } + + if self.max_field_align >= layout.align { + return false; + } + + // We can only generate up-to a 8-bytes of alignment unless we support + // repr(align). + repr_align || layout.align <= MAX_GUARANTEED_ALIGN + } + + fn padding_bytes(&self, layout: Layout) -> usize { + align_to(self.latest_offset, layout.align) - self.latest_offset + } + + fn padding_field(&mut self, layout: Layout) -> proc_macro2::TokenStream { + let ty = helpers::blob(self.ctx, layout, false); + let padding_count = self.padding_count; + + self.padding_count += 1; + + let padding_field_name = Ident::new( + &format!("__bindgen_padding_{padding_count}"), + Span::call_site(), + ); + + self.max_field_align = cmp::max(self.max_field_align, layout.align); + + let vis = super::access_specifier(self.visibility); + + quote! { + #vis #padding_field_name : #ty , + } + } + + /// Returns whether the new field is known to merge with a bitfield. + /// + /// This is just to avoid doing the same check also in `pad_field`. + fn align_to_latest_field(&mut self, new_field_layout: Layout) -> bool { + if self.is_packed { + // Skip to align fields when packed. + return false; + } + + let Some(layout) = self.latest_field_layout else { + return false; + }; + + // If it was, we may or may not need to align, depending on what the + // current field alignment and the bitfield size and alignment are. + debug!( + "align_to_bitfield? {}: {layout:?} {new_field_layout:?}", + self.last_field_was_bitfield, + ); + + // Avoid divide-by-zero errors if align is 0. + let align = cmp::max(1, layout.align); + + if self.last_field_was_bitfield && + new_field_layout.align <= layout.size % align && + new_field_layout.size <= layout.size % align + { + // The new field will be coalesced into some of the remaining bits. + // + // FIXME(emilio): I think this may not catch everything? + debug!("Will merge with bitfield"); + return true; + } + + // Else, just align the obvious way. + self.latest_offset += self.padding_bytes(layout); + false + } +} diff --git a/bindgen/deps.rs b/bindgen/deps.rs new file mode 100644 index 0000000000..3f95ac1e89 --- /dev/null +++ b/bindgen/deps.rs @@ -0,0 +1,61 @@ +/// Generating build depfiles from parsed bindings. +use std::{collections::BTreeSet, path::PathBuf}; + +#[derive(Clone, Debug)] +pub(crate) struct DepfileSpec { + pub output_module: String, + pub depfile_path: PathBuf, +} + +impl DepfileSpec { + pub fn write(&self, deps: &BTreeSet>) -> std::io::Result<()> { + std::fs::write(&self.depfile_path, self.to_string(deps)) + } + + fn to_string(&self, deps: &BTreeSet>) -> String { + // Transforms a string by escaping spaces and backslashes. + let escape = |s: &str| s.replace('\\', "\\\\").replace(' ', "\\ "); + + let mut buf = format!("{}:", escape(&self.output_module)); + for file in deps { + buf = format!("{buf} {}", escape(file)); + } + buf + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn escaping_depfile() { + let spec = DepfileSpec { + output_module: "Mod Name".to_owned(), + depfile_path: PathBuf::new(), + }; + + let deps: BTreeSet<_> = vec![ + r"/absolute/path".into(), + r"C:\win\absolute\path".into(), + r"../relative/path".into(), + r"..\win\relative\path".into(), + r"../path/with spaces/in/it".into(), + r"..\win\path\with spaces\in\it".into(), + r"path\with/mixed\separators".into(), + ] + .into_iter() + .collect(); + assert_eq!( + spec.to_string(&deps), + "Mod\\ Name: \ + ../path/with\\ spaces/in/it \ + ../relative/path \ + ..\\\\win\\\\path\\\\with\\ spaces\\\\in\\\\it \ + ..\\\\win\\\\relative\\\\path \ + /absolute/path \ + C:\\\\win\\\\absolute\\\\path \ + path\\\\with/mixed\\\\separators" + ); + } +} diff --git a/bindgen/diagnostics.rs b/bindgen/diagnostics.rs new file mode 100644 index 0000000000..f22402ac0e --- /dev/null +++ b/bindgen/diagnostics.rs @@ -0,0 +1,146 @@ +//! Types and function used to emit pretty diagnostics for `bindgen`. +//! +//! The entry point of this module is the [`Diagnostic`] type. + +use std::fmt::Write; +use std::io::{self, BufRead, BufReader}; +use std::{borrow::Cow, fs::File}; + +use annotate_snippets::{Renderer, Snippet}; + +pub(crate) use annotate_snippets::Level; + +/// A `bindgen` diagnostic. +#[derive(Default)] +pub(crate) struct Diagnostic<'a> { + title: Option<(Cow<'a, str>, Level)>, + slices: Vec>, + footer: Vec<(Cow<'a, str>, Level)>, +} + +impl<'a> Diagnostic<'a> { + /// Add a title to the diagnostic and set its type. + pub(crate) fn with_title( + &mut self, + title: impl Into>, + level: Level, + ) -> &mut Self { + self.title = Some((title.into(), level)); + self + } + + /// Add a slice of source code to the diagnostic. + pub(crate) fn add_slice(&mut self, slice: Slice<'a>) -> &mut Self { + self.slices.push(slice); + self + } + + /// Add a footer annotation to the diagnostic. This annotation will have its own type. + pub(crate) fn add_annotation( + &mut self, + msg: impl Into>, + level: Level, + ) -> &mut Self { + self.footer.push((msg.into(), level)); + self + } + + /// Print this diagnostic. + /// + /// The diagnostic is printed using `cargo:warning` if `bindgen` is being invoked by a build + /// script or using `eprintln` otherwise. + pub(crate) fn display(&self) { + std::thread_local! { + static INVOKED_BY_BUILD_SCRIPT: bool = std::env::var_os("CARGO_CFG_TARGET_ARCH").is_some(); + } + + let mut footer = vec![]; + let mut slices = vec![]; + let snippet = if let Some((msg, level)) = &self.title { + (*level).title(msg) + } else { + return; + }; + + for (msg, level) in &self.footer { + footer.push((*level).title(msg)); + } + + // add additional info that this is generated by bindgen + // so as to not confuse with rustc warnings + footer.push( + Level::Info.title("This diagnostic was generated by bindgen."), + ); + + for slice in &self.slices { + if let Some(source) = &slice.source { + let mut snippet = Snippet::source(source) + .line_start(slice.line.unwrap_or_default()); + if let Some(origin) = &slice.filename { + snippet = snippet.origin(origin); + } + slices.push(snippet); + } + } + + let renderer = Renderer::styled(); + let dl = renderer.render(snippet.snippets(slices).footers(footer)); + + if INVOKED_BY_BUILD_SCRIPT.with(Clone::clone) { + // This is just a hack which hides the `warning:` added by cargo at the beginning of + // every line. This should be fine as our diagnostics already have a colorful title. + // FIXME (pvdrz): Could it be that this doesn't work in other languages? + let hide_warning = "\r \r"; + let string = dl.to_string(); + for line in string.lines() { + println!("cargo:warning={hide_warning}{line}"); + } + } else { + eprintln!("{dl}\n"); + } + } +} + +/// A slice of source code. +#[derive(Default)] +pub(crate) struct Slice<'a> { + source: Option>, + filename: Option, + line: Option, +} + +impl<'a> Slice<'a> { + /// Set the source code. + pub(crate) fn with_source( + &mut self, + source: impl Into>, + ) -> &mut Self { + self.source = Some(source.into()); + self + } + + /// Set the file, line and column. + pub(crate) fn with_location( + &mut self, + mut name: String, + line: usize, + col: usize, + ) -> &mut Self { + write!(name, ":{line}:{col}").expect("Writing to a string cannot fail"); + self.filename = Some(name); + self.line = Some(line); + self + } +} + +pub(crate) fn get_line( + filename: &str, + line: usize, +) -> io::Result> { + let file = BufReader::new(File::open(filename)?); + if let Some(line) = file.lines().nth(line.wrapping_sub(1)) { + return line.map(Some); + } + + Ok(None) +} diff --git a/bindgen/extra_assertions.rs b/bindgen/extra_assertions.rs new file mode 100644 index 0000000000..8526fd42d2 --- /dev/null +++ b/bindgen/extra_assertions.rs @@ -0,0 +1,17 @@ +//! Macros for defining extra assertions that should only be checked in testing +//! and/or CI when the `__testing_only_extra_assertions` feature is enabled. + +/// Simple macro that forwards to assert! when using +/// `__testing_only_extra_assertions`. +macro_rules! extra_assert { + ( $cond:expr ) => { + if cfg!(feature = "__testing_only_extra_assertions") { + assert!($cond); + } + }; + ( $cond:expr , $( $arg:tt )+ ) => { + if cfg!(feature = "__testing_only_extra_assertions") { + assert!($cond, $( $arg )* ) + } + }; +} diff --git a/bindgen/features.rs b/bindgen/features.rs new file mode 100644 index 0000000000..04450bdee5 --- /dev/null +++ b/bindgen/features.rs @@ -0,0 +1,562 @@ +//! Contains code for selecting features + +#![deny(unused_extern_crates)] +#![deny(clippy::missing_docs_in_private_items)] +#![allow(deprecated)] + +use std::str::FromStr; +use std::{fmt, io}; + +/// Represents the version of the Rust language to target. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +pub struct RustTarget(Version); + +impl RustTarget { + /// Create a new [`RustTarget`] for a stable release of Rust. + pub fn stable(minor: u64, patch: u64) -> Result { + let target = Self(Version::Stable(minor, patch)); + + if target < EARLIEST_STABLE_RUST { + return Err(InvalidRustTarget::TooEarly); + } + + Ok(target) + } + + const fn minor(&self) -> Option { + match self.0 { + Version::Nightly => None, + Version::Stable(minor, _) => Some(minor), + } + } + + const fn is_compatible(&self, other: &Self) -> bool { + match (self.0, other.0) { + (Version::Stable(minor, _), Version::Stable(other_minor, _)) => { + // We ignore the patch version number as they only include backwards compatible bug + // fixes. + minor >= other_minor + } + // Nightly is compatible with everything + (Version::Nightly, _) => true, + // No stable release is compatible with nightly + (Version::Stable { .. }, Version::Nightly) => false, + } + } +} + +impl Default for RustTarget { + fn default() -> Self { + // Bindgen from build script: default to generating bindings compatible + // with the Rust version currently performing this build. + #[cfg(not(feature = "__cli"))] + { + use std::env; + use std::iter; + use std::process::Command; + use std::sync::OnceLock; + + static CURRENT_RUST: OnceLock> = OnceLock::new(); + + if let Some(current_rust) = *CURRENT_RUST.get_or_init(|| { + let is_build_script = + env::var_os("CARGO_CFG_TARGET_ARCH").is_some(); + if !is_build_script { + return None; + } + + let rustc = env::var_os("RUSTC")?; + let rustc_wrapper = env::var_os("RUSTC_WRAPPER") + .filter(|wrapper| !wrapper.is_empty()); + let wrapped_rustc = + rustc_wrapper.iter().chain(iter::once(&rustc)); + + let mut is_clippy_driver = false; + loop { + let mut wrapped_rustc = wrapped_rustc.clone(); + let mut command = + Command::new(wrapped_rustc.next().unwrap()); + command.args(wrapped_rustc); + if is_clippy_driver { + command.arg("--rustc"); + } + command.arg("--version"); + + let output = command.output().ok()?; + let string = String::from_utf8(output.stdout).ok()?; + + // Version string like "rustc 1.100.0-beta.5 (f0e1d2c3b 2026-10-17)" + let last_line = string.lines().last().unwrap_or(&string); + let (program, rest) = last_line.trim().split_once(' ')?; + if program != "rustc" { + if program.starts_with("clippy") && !is_clippy_driver { + is_clippy_driver = true; + continue; + } + return None; + } + + let number = rest.split([' ', '-', '+']).next()?; + break RustTarget::from_str(number).ok(); + } + }) { + return current_rust; + } + } + + // Bindgen from CLI, or cannot determine compiler version: default to + // generating bindings compatible with the latest stable release of Rust + // that Bindgen knows about. + LATEST_STABLE_RUST + } +} + +impl fmt::Display for RustTarget { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 { + Version::Stable(minor, patch) => write!(f, "1.{minor}.{patch}"), + Version::Nightly => "nightly".fmt(f), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +enum Version { + Stable(u64, u64), + Nightly, +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub enum InvalidRustTarget { + TooEarly, +} + +impl fmt::Display for InvalidRustTarget { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::TooEarly => write!(f, "the earliest Rust version supported by bindgen is {EARLIEST_STABLE_RUST}"), + } + } +} + +/// This macro defines the Rust editions supported by bindgen. +macro_rules! define_rust_editions { + ($($variant:ident($value:literal) => $minor:literal,)*) => { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] + #[doc = "Represents Rust Edition for the generated bindings"] + pub enum RustEdition { + $( + #[doc = concat!("The ", stringify!($value), " edition of Rust.")] + $variant, + )* + } + + impl FromStr for RustEdition { + type Err = InvalidRustEdition; + + fn from_str(s: &str) -> Result { + match s { + $(stringify!($value) => Ok(Self::$variant),)* + _ => Err(InvalidRustEdition(s.to_owned())), + } + } + } + + impl fmt::Display for RustEdition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + $(Self::$variant => stringify!($value).fmt(f),)* + } + } + } + + impl RustEdition { + pub(crate) const ALL: [Self; [$($value,)*].len()] = [$(Self::$variant,)*]; + + pub(crate) fn is_available(self, target: RustTarget) -> bool { + let Some(minor) = target.minor() else { + return true; + }; + + match self { + $(Self::$variant => $minor <= minor,)* + } + } + } + } +} + +#[derive(Debug)] +pub struct InvalidRustEdition(String); + +impl fmt::Display for InvalidRustEdition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "\"{}\" is not a valid Rust edition", self.0) + } +} + +impl std::error::Error for InvalidRustEdition {} + +define_rust_editions! { + Edition2018(2018) => 31, + Edition2021(2021) => 56, + Edition2024(2024) => 85, +} + +impl RustTarget { + /// Returns the latest edition supported by this target. + pub(crate) fn latest_edition(self) -> RustEdition { + RustEdition::ALL + .iter() + .rev() + .find(|edition| edition.is_available(self)) + .copied() + .expect("bindgen should always support at least one edition") + } +} + +impl Default for RustEdition { + fn default() -> Self { + RustTarget::default().latest_edition() + } +} + +/// This macro defines the [`RustTarget`] and [`RustFeatures`] types. +macro_rules! define_rust_targets { + ( + Nightly => {$($nightly_feature:ident $(($nightly_edition:literal))|* $(: #$issue:literal)?),* $(,)?} $(,)? + $( + $variant:ident($minor:literal) => {$($feature:ident $(($edition:literal))|* $(: #$pull:literal)?),* $(,)?}, + )* + $(,)? + ) => { + + impl RustTarget { + /// The nightly version of Rust, which introduces the following features:" + $(#[doc = concat!( + "- [`", stringify!($nightly_feature), "`]", + "(", $("https://github.com/rust-lang/rust/pull/", stringify!($issue),)* ")", + )])* + #[deprecated = "The use of this constant is deprecated, please use `RustTarget::nightly` instead."] + pub const Nightly: Self = Self::nightly(); + + /// The nightly version of Rust, which introduces the following features:" + $(#[doc = concat!( + "- [`", stringify!($nightly_feature), "`]", + "(", $("https://github.com/rust-lang/rust/pull/", stringify!($issue),)* ")", + )])* + pub const fn nightly() -> Self { + Self(Version::Nightly) + } + + $( + #[doc = concat!("Version 1.", stringify!($minor), " of Rust, which introduced the following features:")] + $(#[doc = concat!( + "- [`", stringify!($feature), "`]", + "(", $("https://github.com/rust-lang/rust/pull/", stringify!($pull),)* ")", + )])* + #[deprecated = "The use of this constant is deprecated, please use `RustTarget::stable` instead."] + pub const $variant: Self = Self(Version::Stable($minor, 0)); + )* + + const fn stable_releases() -> [(Self, u64); [$($minor,)*].len()] { + [$((Self::$variant, $minor),)*] + } + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] + pub(crate) struct RustFeatures { + $($(pub(crate) $feature: bool,)*)* + $(pub(crate) $nightly_feature: bool,)* + } + + impl RustFeatures { + /// Compute the features that must be enabled in a specific Rust target with a specific edition. + pub(crate) fn new(target: RustTarget, edition: RustEdition) -> Self { + let mut features = Self { + $($($feature: false,)*)* + $($nightly_feature: false,)* + }; + + if target.is_compatible(&RustTarget::nightly()) { + $( + let editions: &[RustEdition] = &[$(stringify!($nightly_edition).parse::().ok().expect("invalid edition"),)*]; + + if editions.is_empty() || editions.contains(&edition) { + features.$nightly_feature = true; + } + )* + } + + $( + if target.is_compatible(&RustTarget::$variant) { + $( + let editions: &[RustEdition] = &[$(stringify!($edition).parse::().ok().expect("invalid edition"),)*]; + + if editions.is_empty() || editions.contains(&edition) { + features.$feature = true; + } + )* + } + )* + + features + } + } + }; +} + +// NOTE: When adding or removing features here, make sure to add the stabilization PR +// number for the feature if it has been stabilized or the tracking issue number if the feature is +// not stable. +define_rust_targets! { + Nightly => { + vectorcall_abi: #124485, + ptr_metadata: #81513, + layout_for_ptr: #69835, + }, + Stable_1_82(82) => { + unsafe_extern_blocks: #127921, + }, + Stable_1_77(77) => { + offset_of: #106655, + literal_cstr(2021)|(2024): #117472, + }, + Stable_1_73(73) => { thiscall_abi: #42202 }, + Stable_1_71(71) => { c_unwind_abi: #106075 }, + Stable_1_68(68) => { abi_efiapi: #105795 }, + Stable_1_64(64) => { core_ffi_c: #94503 }, + Stable_1_59(59) => { const_cstr: #54745 }, + Stable_1_51(51) => {}, +} + +/// Latest stable release of Rust that is supported by bindgen +pub const LATEST_STABLE_RUST: RustTarget = { + // FIXME: replace all this code by + // ``` + // RustTarget::stable_releases() + // .into_iter() + // .max_by_key(|(_, m)| m) + // .map(|(t, _)| t) + // .unwrap() + // ``` + // once those operations can be used in constants. + let targets = RustTarget::stable_releases(); + + let mut i = 0; + let mut latest_target = None; + let mut latest_minor = 0; + + while i < targets.len() { + let (target, minor) = targets[i]; + + if latest_minor < minor { + latest_minor = minor; + latest_target = Some(target); + } + + i += 1; + } + + match latest_target { + Some(target) => target, + None => unreachable!(), + } +}; + +/// Earliest stable release of Rust that is supported by bindgen +pub const EARLIEST_STABLE_RUST: RustTarget = { + // FIXME: replace all this code by + // ``` + // RustTarget::stable_releases() + // .into_iter() + // .min_by_key(|(_, m)| m) + // .map(|(t, _)| t) + // .unwrap_or(LATEST_STABLE_RUST) + // ``` + // once those operations can be used in constants. + let targets = RustTarget::stable_releases(); + + let mut i = 0; + let mut earliest_target = None; + let Some(mut earliest_minor) = LATEST_STABLE_RUST.minor() else { + unreachable!() + }; + + while i < targets.len() { + let (target, minor) = targets[i]; + + if earliest_minor > minor { + earliest_minor = minor; + earliest_target = Some(target); + } + + i += 1; + } + + match earliest_target { + Some(target) => target, + None => unreachable!(), + } +}; + +fn invalid_input(input: &str, msg: impl fmt::Display) -> io::Error { + io::Error::new( + io::ErrorKind::InvalidInput, + format!("\"{input}\" is not a valid Rust target, {msg}"), + ) +} + +impl FromStr for RustTarget { + type Err = io::Error; + + fn from_str(input: &str) -> Result { + if input == "nightly" { + return Ok(Self::Nightly); + } + + let Some((major_str, tail)) = input.split_once('.') else { + return Err(invalid_input(input, "accepted values are of the form \"1.71\", \"1.71.1\" or \"nightly\"." ) ); + }; + + if major_str != "1" { + return Err(invalid_input( + input, + "The largest major version of Rust released is \"1\"", + )); + } + + let (minor, patch) = if let Some((minor_str, patch_str)) = + tail.split_once('.') + { + let Ok(minor) = minor_str.parse::() else { + return Err(invalid_input(input, "the minor version number must be an unsigned 64-bit integer")); + }; + let Ok(patch) = patch_str.parse::() else { + return Err(invalid_input(input, "the patch version number must be an unsigned 64-bit integer")); + }; + (minor, patch) + } else { + let Ok(minor) = tail.parse::() else { + return Err(invalid_input(input, "the minor version number must be an unsigned 64-bit integer")); + }; + (minor, 0) + }; + + Self::stable(minor, patch).map_err(|err| invalid_input(input, err)) + } +} + +impl RustFeatures { + /// Compute the features that must be enabled in a specific Rust target with the latest edition + /// available in that target. + pub(crate) fn new_with_latest_edition(target: RustTarget) -> Self { + Self::new(target, target.latest_edition()) + } +} + +impl Default for RustFeatures { + fn default() -> Self { + Self::new_with_latest_edition(RustTarget::default()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn release_versions_for_editions() { + assert_eq!( + "1.51".parse::().unwrap().latest_edition(), + RustEdition::Edition2018 + ); + assert_eq!( + "1.59".parse::().unwrap().latest_edition(), + RustEdition::Edition2021 + ); + assert_eq!( + "1.85".parse::().unwrap().latest_edition(), + RustEdition::Edition2024 + ); + assert_eq!( + "nightly".parse::().unwrap().latest_edition(), + RustEdition::Edition2024 + ); + } + + #[test] + fn target_features() { + let features = + RustFeatures::new_with_latest_edition(RustTarget::Stable_1_71); + assert!( + features.c_unwind_abi && + features.abi_efiapi && + !features.thiscall_abi + ); + + let features = RustFeatures::new( + RustTarget::Stable_1_77, + RustEdition::Edition2018, + ); + assert!(!features.literal_cstr); + + let features = + RustFeatures::new_with_latest_edition(RustTarget::Stable_1_77); + assert!(features.literal_cstr); + + let f_nightly = + RustFeatures::new_with_latest_edition(RustTarget::Nightly); + assert!( + f_nightly.vectorcall_abi && + f_nightly.ptr_metadata && + f_nightly.layout_for_ptr + ); + } + + fn test_target(input: &str, expected: RustTarget) { + // Two targets are equivalent if they enable the same set of features + let expected = RustFeatures::new_with_latest_edition(expected); + let found = RustFeatures::new_with_latest_edition( + input.parse::().unwrap(), + ); + assert_eq!( + expected, + found, + "target {input} enables features:\n{found:#?}\nand should enable features:\n{expected:#?}" + ); + } + + fn test_invalid_target(input: &str) { + assert!( + input.parse::().is_err(), + "{input} should be an invalid target" + ); + } + + #[test] + fn valid_targets() { + test_target("1.71", RustTarget::Stable_1_71); + test_target("1.71.0", RustTarget::Stable_1_71); + test_target("1.71.1", RustTarget::Stable_1_71); + test_target("1.72", RustTarget::Stable_1_71); + test_target("1.73", RustTarget::Stable_1_73); + test_target("1.18446744073709551615", LATEST_STABLE_RUST); + test_target("nightly", RustTarget::Nightly); + } + + #[test] + fn invalid_targets() { + test_invalid_target("2.0"); + test_invalid_target("1.cat"); + test_invalid_target("1.0.cat"); + test_invalid_target("1.18446744073709551616"); + test_invalid_target("1.0.18446744073709551616"); + test_invalid_target("1.-1.0"); + test_invalid_target("1.0.-1"); + test_invalid_target("beta"); + test_invalid_target("1.0.0"); + test_invalid_target("1.32.0"); + } +} diff --git a/bindgen/ir/analysis/derive.rs b/bindgen/ir/analysis/derive.rs new file mode 100644 index 0000000000..7316950ba2 --- /dev/null +++ b/bindgen/ir/analysis/derive.rs @@ -0,0 +1,693 @@ +//! Determining which types for which we cannot emit `#[derive(Trait)]`. + +use std::fmt; + +use super::{generate_dependencies, ConstrainResult, MonotoneFramework}; +use crate::ir::analysis::has_vtable::HasVtable; +use crate::ir::comp::CompKind; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::derive::CanDerive; +use crate::ir::function::FunctionSig; +use crate::ir::item::{IsOpaque, Item}; +use crate::ir::layout::Layout; +use crate::ir::template::TemplateParameters; +use crate::ir::traversal::{EdgeKind, Trace}; +use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; +use crate::ir::ty::{Type, TypeKind}; +use crate::{Entry, HashMap, HashSet}; + +/// Which trait to consider when doing the `CannotDerive` analysis. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum DeriveTrait { + /// The `Copy` trait. + Copy, + /// The `Debug` trait. + Debug, + /// The `Default` trait. + Default, + /// The `Hash` trait. + Hash, + /// The `PartialEq` and `PartialOrd` traits. + PartialEqOrPartialOrd, +} + +/// An analysis that finds for each IR item whether a trait cannot be derived. +/// +/// We use the monotone constraint function `cannot_derive`, defined as follows +/// for type T: +/// +/// * If T is Opaque and the layout of the type is known, get this layout as an +/// opaquetype and check whether it can derive using trivial checks. +/// +/// * If T is Array, a trait cannot be derived if the array is incomplete, +/// if the length of the array is larger than the limit (unless the trait +/// allows it), or the trait cannot be derived for the type of data the array +/// contains. +/// +/// * If T is Vector, a trait cannot be derived if the trait cannot be derived +/// for the type of data the vector contains. +/// +/// * If T is a type alias, a templated alias or an indirection to another type, +/// the trait cannot be derived if the trait cannot be derived for type T +/// refers to. +/// +/// * If T is a compound type, the trait cannot be derived if the trait cannot +/// be derived for any of its base members or fields. +/// +/// * If T is an instantiation of an abstract template definition, the trait +/// cannot be derived if any of the template arguments or template definition +/// cannot derive the trait. +/// +/// * For all other (simple) types, compiler and standard library limitations +/// dictate whether the trait is implemented. +#[derive(Debug, Clone)] +pub(crate) struct CannotDerive<'ctx> { + ctx: &'ctx BindgenContext, + + derive_trait: DeriveTrait, + + // The incremental result of this analysis's computation. + // Contains information whether particular item can derive `derive_trait` + can_derive: HashMap, + + // Dependencies saying that if a key ItemId has been inserted into the + // `cannot_derive_partialeq_or_partialord` set, then each of the ids + // in Vec need to be considered again. + // + // This is a subset of the natural IR graph with reversed edges, where we + // only include the edges from the IR graph that can affect whether a type + // can derive `derive_trait`. + dependencies: HashMap>, +} + +type EdgePredicate = fn(EdgeKind) -> bool; + +fn consider_edge_default(kind: EdgeKind) -> bool { + match kind { + // These are the only edges that can affect whether a type can derive + EdgeKind::BaseMember | + EdgeKind::Field | + EdgeKind::TypeReference | + EdgeKind::VarType | + EdgeKind::TemplateArgument | + EdgeKind::TemplateDeclaration | + EdgeKind::TemplateParameterDefinition => true, + + EdgeKind::Constructor | + EdgeKind::Destructor | + EdgeKind::FunctionReturn | + EdgeKind::FunctionParameter | + EdgeKind::InnerType | + EdgeKind::InnerVar | + EdgeKind::Method | + EdgeKind::Generic => false, + } +} + +impl CannotDerive<'_> { + fn insert>( + &mut self, + id: Id, + can_derive: CanDerive, + ) -> ConstrainResult { + let id = id.into(); + trace!( + "inserting {id:?} can_derive<{}>={can_derive:?}", + self.derive_trait, + ); + + if let CanDerive::Yes = can_derive { + return ConstrainResult::Same; + } + + match self.can_derive.entry(id) { + Entry::Occupied(mut entry) => { + if *entry.get() < can_derive { + entry.insert(can_derive); + ConstrainResult::Changed + } else { + ConstrainResult::Same + } + } + Entry::Vacant(entry) => { + entry.insert(can_derive); + ConstrainResult::Changed + } + } + } + + fn constrain_type(&mut self, item: &Item, ty: &Type) -> CanDerive { + if !self.ctx.allowlisted_items().contains(&item.id()) { + let can_derive = self + .ctx + .blocklisted_type_implements_trait(item, self.derive_trait); + match can_derive { + CanDerive::Yes => trace!( + " blocklisted type explicitly implements {}", + self.derive_trait + ), + CanDerive::Manually => trace!( + " blocklisted type requires manual implementation of {}", + self.derive_trait + ), + CanDerive::No => trace!( + " cannot derive {} for blocklisted type", + self.derive_trait + ), + } + return can_derive; + } + + if self.derive_trait.not_by_name(self.ctx, item) { + trace!( + " cannot derive {} for explicitly excluded type", + self.derive_trait + ); + return CanDerive::No; + } + + trace!("ty: {ty:?}"); + if item.is_opaque(self.ctx, &()) { + if !self.derive_trait.can_derive_union() && + ty.is_union() && + self.ctx.options().untagged_union + { + trace!( + " cannot derive {} for Rust unions", + self.derive_trait + ); + return CanDerive::No; + } + + trace!( + " we can trivially derive {} for the layout", + self.derive_trait + ); + return CanDerive::Yes; + } + + match *ty.kind() { + // Handle the simple cases. These can derive traits without further + // information. + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Complex(..) | + TypeKind::Float(..) | + TypeKind::Enum(..) | + TypeKind::TypeParam | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::Reference(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel => self.derive_trait.can_derive_simple(ty.kind()), + TypeKind::Pointer(inner) => { + let inner_type = + self.ctx.resolve_type(inner).canonical_type(self.ctx); + if let TypeKind::Function(ref sig) = *inner_type.kind() { + self.derive_trait.can_derive_fnptr(sig) + } else { + self.derive_trait.can_derive_pointer() + } + } + TypeKind::Function(ref sig) => { + self.derive_trait.can_derive_fnptr(sig) + } + + // Complex cases need more information + TypeKind::Array(t, len) => { + let inner_type = + self.can_derive.get(&t.into()).copied().unwrap_or_default(); + if inner_type != CanDerive::Yes { + trace!( + " arrays of T for which we cannot derive {} \ + also cannot derive {}", + self.derive_trait, + self.derive_trait + ); + return CanDerive::No; + } + + if len == 0 && !self.derive_trait.can_derive_incomplete_array() + { + trace!( + " cannot derive {} for incomplete arrays", + self.derive_trait + ); + return CanDerive::No; + } + + if self.derive_trait.can_derive_large_array(self.ctx) { + trace!(" array can derive {}", self.derive_trait); + return CanDerive::Yes; + } + + if len > RUST_DERIVE_IN_ARRAY_LIMIT { + trace!( + " array is too large to derive {}, but it may be implemented", self.derive_trait + ); + return CanDerive::Manually; + } + trace!( + " array is small enough to derive {}", + self.derive_trait + ); + CanDerive::Yes + } + TypeKind::Vector(t, len) => { + let inner_type = + self.can_derive.get(&t.into()).copied().unwrap_or_default(); + if inner_type != CanDerive::Yes { + trace!( + " vectors of T for which we cannot derive {} \ + also cannot derive {}", + self.derive_trait, + self.derive_trait + ); + return CanDerive::No; + } + assert_ne!(len, 0, "vectors cannot have zero length"); + self.derive_trait.can_derive_vector() + } + + TypeKind::Comp(ref info) => { + assert!( + !info.has_non_type_template_params(), + "The early ty.is_opaque check should have handled this case" + ); + + if !self.derive_trait.can_derive_compound_forward_decl() && + info.is_forward_declaration() + { + trace!( + " cannot derive {} for forward decls", + self.derive_trait + ); + return CanDerive::No; + } + + // NOTE: Take into account that while unions in C and C++ are copied by + // default, the may have an explicit destructor in C++, so we can't + // defer this check just for the union case. + if !self.derive_trait.can_derive_compound_with_destructor() && + self.ctx.lookup_has_destructor( + item.id().expect_type_id(self.ctx), + ) + { + trace!( + " comp has destructor which cannot derive {}", + self.derive_trait + ); + return CanDerive::No; + } + + if info.kind() == CompKind::Union { + if self.derive_trait.can_derive_union() { + if self.ctx.options().untagged_union && + // https://github.com/rust-lang/rust/issues/36640 + (!info.self_template_params(self.ctx).is_empty() || + !item.all_template_params(self.ctx).is_empty()) + { + trace!( + " cannot derive {} for Rust union because issue 36640", self.derive_trait + ); + return CanDerive::No; + } + // fall through to be same as non-union handling + } else { + if self.ctx.options().untagged_union { + trace!( + " cannot derive {} for Rust unions", + self.derive_trait + ); + return CanDerive::No; + } + + trace!( + " union layout can trivially derive {}", + self.derive_trait + ); + return CanDerive::Yes; + } + } + + if !self.derive_trait.can_derive_compound_with_vtable() && + item.has_vtable(self.ctx) + { + trace!( + " cannot derive {} for comp with vtable", + self.derive_trait + ); + return CanDerive::No; + } + + // Bitfield units are always represented as arrays of u8, but + // they're not traced as arrays, so we need to check here + // instead. + if !self.derive_trait.can_derive_large_array(self.ctx) && + info.has_too_large_bitfield_unit() && + !item.is_opaque(self.ctx, &()) + { + trace!( + " cannot derive {} for comp with too large bitfield unit", + self.derive_trait + ); + return CanDerive::No; + } + + let pred = self.derive_trait.consider_edge_comp(); + self.constrain_join(item, pred) + } + + TypeKind::ResolvedTypeRef(..) | + TypeKind::TemplateAlias(..) | + TypeKind::Alias(..) | + TypeKind::BlockPointer(..) => { + let pred = self.derive_trait.consider_edge_typeref(); + self.constrain_join(item, pred) + } + + TypeKind::TemplateInstantiation(..) => { + let pred = self.derive_trait.consider_edge_tmpl_inst(); + self.constrain_join(item, pred) + } + + TypeKind::Opaque => unreachable!( + "The early ty.is_opaque check should have handled this case" + ), + } + } + + fn constrain_join( + &mut self, + item: &Item, + consider_edge: EdgePredicate, + ) -> CanDerive { + let mut candidate = None; + + item.trace( + self.ctx, + &mut |sub_id, edge_kind| { + // Ignore ourselves, since union with ourself is a + // no-op. Ignore edges that aren't relevant to the + // analysis. + if sub_id == item.id() || !consider_edge(edge_kind) { + return; + } + + let can_derive = self.can_derive + .get(&sub_id) + .copied() + .unwrap_or_default(); + + match can_derive { + CanDerive::Yes => trace!(" member {sub_id:?} can derive {}", self.derive_trait), + CanDerive::Manually => trace!(" member {sub_id:?} cannot derive {}, but it may be implemented", self.derive_trait), + CanDerive::No => trace!(" member {sub_id:?} cannot derive {}", self.derive_trait), + } + + *candidate.get_or_insert(CanDerive::Yes) |= can_derive; + }, + &(), + ); + + if candidate.is_none() { + trace!( + " can derive {} because there are no members", + self.derive_trait + ); + } + candidate.unwrap_or_default() + } +} + +impl DeriveTrait { + fn not_by_name(self, ctx: &BindgenContext, item: &Item) -> bool { + match self { + DeriveTrait::Copy => ctx.no_copy_by_name(item), + DeriveTrait::Debug => ctx.no_debug_by_name(item), + DeriveTrait::Default => ctx.no_default_by_name(item), + DeriveTrait::Hash => ctx.no_hash_by_name(item), + DeriveTrait::PartialEqOrPartialOrd => { + ctx.no_partialeq_by_name(item) + } + } + } + + fn consider_edge_comp(self) -> EdgePredicate { + match self { + DeriveTrait::PartialEqOrPartialOrd => consider_edge_default, + _ => |kind| matches!(kind, EdgeKind::BaseMember | EdgeKind::Field), + } + } + + fn consider_edge_typeref(self) -> EdgePredicate { + match self { + DeriveTrait::PartialEqOrPartialOrd => consider_edge_default, + _ => |kind| kind == EdgeKind::TypeReference, + } + } + + fn consider_edge_tmpl_inst(self) -> EdgePredicate { + match self { + DeriveTrait::PartialEqOrPartialOrd => consider_edge_default, + _ => |kind| { + matches!( + kind, + EdgeKind::TemplateArgument | EdgeKind::TemplateDeclaration + ) + }, + } + } + + fn can_derive_large_array(self, _: &BindgenContext) -> bool { + !matches!(self, DeriveTrait::Default) + } + + fn can_derive_union(self) -> bool { + matches!(self, DeriveTrait::Copy) + } + + fn can_derive_compound_with_destructor(self) -> bool { + !matches!(self, DeriveTrait::Copy) + } + + fn can_derive_compound_with_vtable(self) -> bool { + !matches!(self, DeriveTrait::Default) + } + + fn can_derive_compound_forward_decl(self) -> bool { + matches!(self, DeriveTrait::Copy | DeriveTrait::Debug) + } + + fn can_derive_incomplete_array(self) -> bool { + !matches!( + self, + DeriveTrait::Copy | + DeriveTrait::Hash | + DeriveTrait::PartialEqOrPartialOrd + ) + } + + fn can_derive_fnptr(self, f: &FunctionSig) -> CanDerive { + match (self, f.function_pointers_can_derive()) { + (DeriveTrait::Copy | DeriveTrait::Default, _) | (_, true) => { + trace!(" function pointer can derive {self}"); + CanDerive::Yes + } + (DeriveTrait::Debug, false) => { + trace!(" function pointer cannot derive {self}, but it may be implemented"); + CanDerive::Manually + } + (_, false) => { + trace!(" function pointer cannot derive {self}"); + CanDerive::No + } + } + } + + fn can_derive_vector(self) -> CanDerive { + if self == DeriveTrait::PartialEqOrPartialOrd { + // FIXME: vectors always can derive PartialEq, but they should + // not derive PartialOrd: + // https://github.com/rust-lang-nursery/packed_simd/issues/48 + trace!(" vectors cannot derive PartialOrd"); + CanDerive::No + } else { + trace!(" vector can derive {self}"); + CanDerive::Yes + } + } + + fn can_derive_pointer(self) -> CanDerive { + if self == DeriveTrait::Default { + trace!(" pointer cannot derive Default"); + CanDerive::No + } else { + trace!(" pointer can derive {self}"); + CanDerive::Yes + } + } + + fn can_derive_simple(self, kind: &TypeKind) -> CanDerive { + match (self, kind) { + // === Default === + ( + DeriveTrait::Default, + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::TypeParam | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel, + ) => { + trace!(" types that always cannot derive Default"); + CanDerive::No + } + (DeriveTrait::Default, TypeKind::UnresolvedTypeRef(..)) => { + unreachable!( + "Type with unresolved type ref can't reach derive default" + ) + } + // === Hash === + ( + DeriveTrait::Hash, + TypeKind::Float(..) | TypeKind::Complex(..), + ) => { + trace!(" float cannot derive Hash"); + CanDerive::No + } + // === others === + _ => { + trace!(" simple type that can always derive {self}"); + CanDerive::Yes + } + } + } +} + +impl fmt::Display for DeriveTrait { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match self { + DeriveTrait::Copy => "Copy", + DeriveTrait::Debug => "Debug", + DeriveTrait::Default => "Default", + DeriveTrait::Hash => "Hash", + DeriveTrait::PartialEqOrPartialOrd => "PartialEq/PartialOrd", + }; + s.fmt(f) + } +} + +impl<'ctx> MonotoneFramework for CannotDerive<'ctx> { + type Node = ItemId; + type Extra = (&'ctx BindgenContext, DeriveTrait); + type Output = HashMap; + + fn new( + (ctx, derive_trait): (&'ctx BindgenContext, DeriveTrait), + ) -> CannotDerive<'ctx> { + let can_derive = HashMap::default(); + let dependencies = generate_dependencies(ctx, consider_edge_default); + + CannotDerive { + ctx, + derive_trait, + can_derive, + dependencies, + } + } + + fn initial_worklist(&self) -> Vec { + // The transitive closure of all allowlisted items, including explicitly + // blocklisted items. + self.ctx + .allowlisted_items() + .iter() + .copied() + .flat_map(|i| { + let mut reachable = vec![i]; + i.trace( + self.ctx, + &mut |s, _| { + reachable.push(s); + }, + &(), + ); + reachable + }) + .collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + trace!("constrain: {id:?}"); + + if let Some(CanDerive::No) = self.can_derive.get(&id) { + trace!(" already know it cannot derive {}", self.derive_trait); + return ConstrainResult::Same; + } + + let item = self.ctx.resolve_item(id); + let can_derive = match item.as_type() { + Some(ty) => { + let mut can_derive = self.constrain_type(item, ty); + if let CanDerive::Yes = can_derive { + let is_reached_limit = + |l: Layout| l.align > RUST_DERIVE_IN_ARRAY_LIMIT; + if !self.derive_trait.can_derive_large_array(self.ctx) && + ty.layout(self.ctx).is_some_and(is_reached_limit) + { + // We have to be conservative: the struct *could* have enough + // padding that we emit an array that is longer than + // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations + // into the IR and computed them before this analysis, then we could + // be precise rather than conservative here. + can_derive = CanDerive::Manually; + } + } + can_derive + } + None => self.constrain_join(item, consider_edge_default), + }; + + self.insert(id, can_derive) + } + + fn each_depending_on(&self, id: ItemId, mut f: F) + where + F: FnMut(ItemId), + { + if let Some(edges) = self.dependencies.get(&id) { + for item in edges { + trace!("enqueue {item:?} into worklist"); + f(*item); + } + } + } +} + +impl<'ctx> From> for HashMap { + fn from(analysis: CannotDerive<'ctx>) -> Self { + extra_assert!(analysis + .can_derive + .values() + .all(|v| *v != CanDerive::Yes)); + + analysis.can_derive + } +} + +/// Convert a `HashMap` into a `HashSet`. +/// +/// Elements that are not `CanDerive::Yes` are kept in the set, so that it +/// represents all items that cannot derive. +pub(crate) fn as_cannot_derive_set( + can_derive: HashMap, +) -> HashSet { + can_derive + .into_iter() + .filter_map(|(k, v)| if v == CanDerive::Yes { None } else { Some(k) }) + .collect() +} diff --git a/src/ir/analysis/has_destructor.rs b/bindgen/ir/analysis/has_destructor.rs similarity index 76% rename from src/ir/analysis/has_destructor.rs rename to bindgen/ir/analysis/has_destructor.rs index c87b7e2580..44ef33c21b 100644 --- a/src/ir/analysis/has_destructor.rs +++ b/bindgen/ir/analysis/has_destructor.rs @@ -1,12 +1,11 @@ //! Determining which types have destructors -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::context::{BindgenContext, ItemId}; -use ir::traversal::EdgeKind; -use ir::comp::{CompKind, Field, FieldMethods}; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; +use super::{generate_dependencies, ConstrainResult, MonotoneFramework}; +use crate::ir::comp::{CompKind, Field, FieldMethods}; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::traversal::EdgeKind; +use crate::ir::ty::TypeKind; +use crate::{HashMap, HashSet}; /// An analysis that finds for each IR item whether it has a destructor or not /// @@ -23,7 +22,7 @@ use std::collections::HashSet; /// * If T is the type of a field, that field has a destructor if it's not a bitfield, /// and if T has a destructor. #[derive(Debug, Clone)] -pub struct HasDestructorAnalysis<'ctx> { +pub(crate) struct HasDestructorAnalysis<'ctx> { ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this @@ -40,18 +39,18 @@ pub struct HasDestructorAnalysis<'ctx> { dependencies: HashMap>, } -impl<'ctx> HasDestructorAnalysis<'ctx> { +impl HasDestructorAnalysis<'_> { fn consider_edge(kind: EdgeKind) -> bool { - match kind { - // These are the only edges that can affect whether a type has a - // destructor or not. + // These are the only edges that can affect whether a type has a + // destructor or not. + matches!( + kind, EdgeKind::TypeReference | - EdgeKind::BaseMember | - EdgeKind::Field | - EdgeKind::TemplateArgument | - EdgeKind::TemplateDeclaration => true, - _ => false, - } + EdgeKind::BaseMember | + EdgeKind::Field | + EdgeKind::TemplateArgument | + EdgeKind::TemplateDeclaration + ) } fn insert>(&mut self, id: Id) -> ConstrainResult { @@ -59,9 +58,8 @@ impl<'ctx> HasDestructorAnalysis<'ctx> { let was_not_already_in_set = self.have_destructor.insert(id); assert!( was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id + "We shouldn't try and insert {id:?} twice because if it was \ + already in the set, `constrain` should have exited early." ); ConstrainResult::Changed } @@ -73,7 +71,7 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { type Output = HashSet; fn new(ctx: &'ctx BindgenContext) -> Self { - let have_destructor = HashSet::new(); + let have_destructor = HashSet::default(); let dependencies = generate_dependencies(ctx, Self::consider_edge); HasDestructorAnalysis { @@ -84,7 +82,7 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { } fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().copied().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { @@ -95,9 +93,8 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { } let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - None => return ConstrainResult::Same, - Some(ty) => ty, + let Some(ty) = item.as_type() else { + return ConstrainResult::Same; }; match *ty.kind() { @@ -122,14 +119,14 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { let base_or_field_destructor = info.base_members().iter().any(|base| { self.have_destructor.contains(&base.ty.into()) - }) || - info.fields().iter().any(|field| { - match *field { - Field::DataMember(ref data) => - self.have_destructor.contains(&data.ty().into()), - Field::Bitfields(_) => false - } - }); + }) || info.fields().iter().any( + |field| match *field { + Field::DataMember(ref data) => self + .have_destructor + .contains(&data.ty().into()), + Field::Bitfields(_) => false, + }, + ); if base_or_field_destructor { self.insert(id) } else { @@ -140,9 +137,9 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { } TypeKind::TemplateInstantiation(ref inst) => { - let definition_or_arg_destructor = - self.have_destructor.contains(&inst.template_definition().into()) - || + let definition_or_arg_destructor = self + .have_destructor + .contains(&inst.template_definition().into()) || inst.template_arguments().iter().any(|arg| { self.have_destructor.contains(&arg.into()) }); @@ -163,7 +160,7 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { { if let Some(edges) = self.dependencies.get(&id) { for item in edges { - trace!("enqueue {:?} into worklist", item); + trace!("enqueue {item:?} into worklist"); f(*item); } } diff --git a/bindgen/ir/analysis/has_float.rs b/bindgen/ir/analysis/has_float.rs new file mode 100644 index 0000000000..e2463ccb96 --- /dev/null +++ b/bindgen/ir/analysis/has_float.rs @@ -0,0 +1,248 @@ +//! Determining which types has float. + +use super::{generate_dependencies, ConstrainResult, MonotoneFramework}; +use crate::ir::comp::Field; +use crate::ir::comp::FieldMethods; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::traversal::EdgeKind; +use crate::ir::ty::TypeKind; +use crate::{HashMap, HashSet}; + +/// An analysis that finds for each IR item whether it has float or not. +/// +/// We use the monotone constraint function `has_float`, +/// defined as follows: +/// +/// * If T is float or complex float, T trivially has. +/// * If T is a type alias, a templated alias or an indirection to another type, +/// it has float if the type T refers to has. +/// * If T is a compound type, it has float if any of base memter or field +/// has. +/// * If T is an instantiation of an abstract template definition, T has +/// float if any of the template arguments or template definition +/// has. +#[derive(Debug, Clone)] +pub(crate) struct HasFloat<'ctx> { + ctx: &'ctx BindgenContext, + + // The incremental result of this analysis's computation. Everything in this + // set has float. + has_float: HashSet, + + // Dependencies saying that if a key ItemId has been inserted into the + // `has_float` set, then each of the ids in Vec need to be + // considered again. + // + // This is a subset of the natural IR graph with reversed edges, where we + // only include the edges from the IR graph that can affect whether a type + // has float or not. + dependencies: HashMap>, +} + +impl HasFloat<'_> { + fn consider_edge(kind: EdgeKind) -> bool { + match kind { + EdgeKind::BaseMember | + EdgeKind::Field | + EdgeKind::TypeReference | + EdgeKind::VarType | + EdgeKind::TemplateArgument | + EdgeKind::TemplateDeclaration | + EdgeKind::TemplateParameterDefinition => true, + + EdgeKind::Constructor | + EdgeKind::Destructor | + EdgeKind::FunctionReturn | + EdgeKind::FunctionParameter | + EdgeKind::InnerType | + EdgeKind::InnerVar | + EdgeKind::Method | + EdgeKind::Generic => false, + } + } + + fn insert>(&mut self, id: Id) -> ConstrainResult { + let id = id.into(); + trace!("inserting {id:?} into the has_float set"); + + let was_not_already_in_set = self.has_float.insert(id); + assert!( + was_not_already_in_set, + "We shouldn't try and insert {id:?} twice because if it was \ + already in the set, `constrain` should have exited early." + ); + + ConstrainResult::Changed + } +} + +impl<'ctx> MonotoneFramework for HasFloat<'ctx> { + type Node = ItemId; + type Extra = &'ctx BindgenContext; + type Output = HashSet; + + fn new(ctx: &'ctx BindgenContext) -> HasFloat<'ctx> { + let has_float = HashSet::default(); + let dependencies = generate_dependencies(ctx, Self::consider_edge); + + HasFloat { + ctx, + has_float, + dependencies, + } + } + + fn initial_worklist(&self) -> Vec { + self.ctx.allowlisted_items().iter().copied().collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + trace!("constrain: {id:?}"); + + if self.has_float.contains(&id) { + trace!(" already know it do not have float"); + return ConstrainResult::Same; + } + + let item = self.ctx.resolve_item(id); + let Some(ty) = item.as_type() else { + trace!(" not a type; ignoring"); + return ConstrainResult::Same; + }; + + match *ty.kind() { + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::TypeParam | + TypeKind::Opaque | + TypeKind::Pointer(..) | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel => { + trace!(" simple type that do not have float"); + ConstrainResult::Same + } + + TypeKind::Float(..) | TypeKind::Complex(..) => { + trace!(" float type has float"); + self.insert(id) + } + + TypeKind::Array(t, _) => { + if self.has_float.contains(&t.into()) { + trace!( + " Array with type T that has float also has float" + ); + return self.insert(id); + } + trace!(" Array with type T that do not have float also do not have float"); + ConstrainResult::Same + } + TypeKind::Vector(t, _) => { + if self.has_float.contains(&t.into()) { + trace!( + " Vector with type T that has float also has float" + ); + return self.insert(id); + } + trace!(" Vector with type T that do not have float also do not have float"); + ConstrainResult::Same + } + + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::BlockPointer(t) => { + if self.has_float.contains(&t.into()) { + trace!( + " aliases and type refs to T which have float \ + also have float" + ); + self.insert(id) + } else { + trace!(" aliases and type refs to T which do not have float \ + also do not have floaarrayt"); + ConstrainResult::Same + } + } + + TypeKind::Comp(ref info) => { + let bases_have = info + .base_members() + .iter() + .any(|base| self.has_float.contains(&base.ty.into())); + if bases_have { + trace!(" bases have float, so we also have"); + return self.insert(id); + } + let fields_have = info.fields().iter().any(|f| match *f { + Field::DataMember(ref data) => { + self.has_float.contains(&data.ty().into()) + } + Field::Bitfields(ref bfu) => bfu + .bitfields() + .iter() + .any(|b| self.has_float.contains(&b.ty().into())), + }); + if fields_have { + trace!(" fields have float, so we also have"); + return self.insert(id); + } + + trace!(" comp doesn't have float"); + ConstrainResult::Same + } + + TypeKind::TemplateInstantiation(ref template) => { + let args_have = template + .template_arguments() + .iter() + .any(|arg| self.has_float.contains(&arg.into())); + if args_have { + trace!( + " template args have float, so \ + instantiation also has float" + ); + return self.insert(id); + } + + let def_has = self + .has_float + .contains(&template.template_definition().into()); + if def_has { + trace!( + " template definition has float, so \ + instantiation also has" + ); + return self.insert(id); + } + + trace!(" template instantiation do not have float"); + ConstrainResult::Same + } + } + } + + fn each_depending_on(&self, id: ItemId, mut f: F) + where + F: FnMut(ItemId), + { + if let Some(edges) = self.dependencies.get(&id) { + for item in edges { + trace!("enqueue {item:?} into worklist"); + f(*item); + } + } + } +} + +impl<'ctx> From> for HashSet { + fn from(analysis: HasFloat<'ctx>) -> Self { + analysis.has_float + } +} diff --git a/src/ir/analysis/has_type_param_in_array.rs b/bindgen/ir/analysis/has_type_param_in_array.rs similarity index 75% rename from src/ir/analysis/has_type_param_in_array.rs rename to bindgen/ir/analysis/has_type_param_in_array.rs index aa8d34be9a..687f81560c 100644 --- a/src/ir/analysis/has_type_param_in_array.rs +++ b/bindgen/ir/analysis/has_type_param_in_array.rs @@ -1,13 +1,12 @@ //! Determining which types has typed parameters in array. -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::Field; -use ir::comp::FieldMethods; -use ir::context::{BindgenContext, ItemId}; -use ir::traversal::EdgeKind; -use ir::ty::TypeKind; -use std::collections::HashMap; -use std::collections::HashSet; +use super::{generate_dependencies, ConstrainResult, MonotoneFramework}; +use crate::ir::comp::Field; +use crate::ir::comp::FieldMethods; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::traversal::EdgeKind; +use crate::ir::ty::TypeKind; +use crate::{HashMap, HashSet}; /// An analysis that finds for each IR item whether it has array or not. /// @@ -18,12 +17,12 @@ use std::collections::HashSet; /// * If T is a type alias, a templated alias or an indirection to another type, /// it has type parameter in array if the type T refers to has. /// * If T is a compound type, it has array if any of base memter or field -/// has type paramter in array. +/// has type parameter in array. /// * If T is an instantiation of an abstract template definition, T has /// type parameter in array if any of the template arguments or template definition /// has. #[derive(Debug, Clone)] -pub struct HasTypeParameterInArray<'ctx> { +pub(crate) struct HasTypeParameterInArray<'ctx> { ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this @@ -40,7 +39,7 @@ pub struct HasTypeParameterInArray<'ctx> { dependencies: HashMap>, } -impl<'ctx> HasTypeParameterInArray<'ctx> { +impl HasTypeParameterInArray<'_> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type has type parameter @@ -59,25 +58,21 @@ impl<'ctx> HasTypeParameterInArray<'ctx> { EdgeKind::FunctionParameter | EdgeKind::InnerType | EdgeKind::InnerVar | - EdgeKind::Method => false, + EdgeKind::Method | EdgeKind::Generic => false, } } fn insert>(&mut self, id: Id) -> ConstrainResult { let id = id.into(); - trace!( - "inserting {:?} into the has_type_parameter_in_array set", - id - ); + trace!("inserting {id:?} into the has_type_parameter_in_array set"); let was_not_already_in_set = self.has_type_parameter_in_array.insert(id); assert!( was_not_already_in_set, - "We shouldn't try and insert {:?} twice because if it was \ - already in the set, `constrain` should have exited early.", - id + "We shouldn't try and insert {id:?} twice because if it was \ + already in the set, `constrain` should have exited early." ); ConstrainResult::Changed @@ -89,10 +84,8 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { type Extra = &'ctx BindgenContext; type Output = HashSet; - fn new( - ctx: &'ctx BindgenContext, - ) -> HasTypeParameterInArray<'ctx> { - let has_type_parameter_in_array = HashSet::new(); + fn new(ctx: &'ctx BindgenContext) -> HasTypeParameterInArray<'ctx> { + let has_type_parameter_in_array = HashSet::default(); let dependencies = generate_dependencies(ctx, Self::consider_edge); HasTypeParameterInArray { @@ -103,11 +96,11 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { } fn initial_worklist(&self) -> Vec { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().copied().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); + trace!("constrain: {id:?}"); if self.has_type_parameter_in_array.contains(&id) { trace!(" already know it do not have array"); @@ -115,12 +108,9 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { } let item = self.ctx.resolve_item(id); - let ty = match item.as_type() { - Some(ty) => ty, - None => { - trace!(" not a type; ignoring"); - return ConstrainResult::Same; - } + let Some(ty) = item.as_type() else { + trace!(" not a type; ignoring"); + return ConstrainResult::Same; }; match *ty.kind() { @@ -130,11 +120,11 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { TypeKind::NullPtr | TypeKind::Int(..) | TypeKind::Float(..) | + TypeKind::Vector(..) | TypeKind::Complex(..) | TypeKind::Function(..) | TypeKind::Enum(..) | TypeKind::Reference(..) | - TypeKind::BlockPointer | TypeKind::TypeParam | TypeKind::Opaque | TypeKind::Pointer(..) | @@ -149,27 +139,25 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { TypeKind::Array(t, _) => { let inner_ty = self.ctx.resolve_type(t).canonical_type(self.ctx); - match *inner_ty.kind() { - TypeKind::TypeParam => { - trace!(" Array with Named type has type parameter"); - self.insert(id) - } - _ => { - trace!( - " Array without Named type does have type parameter" - ); - ConstrainResult::Same - } + if let TypeKind::TypeParam = *inner_ty.kind() { + trace!(" Array with Named type has type parameter"); + self.insert(id) + } else { + trace!( + " Array without Named type does have type parameter" + ); + ConstrainResult::Same } } TypeKind::ResolvedTypeRef(t) | TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => { + TypeKind::Alias(t) | + TypeKind::BlockPointer(t) => { if self.has_type_parameter_in_array.contains(&t.into()) { trace!( " aliases and type refs to T which have array \ - also have array" + also have array" ); self.insert(id) } else { @@ -190,9 +178,9 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { return self.insert(id); } let fields_have = info.fields().iter().any(|f| match *f { - Field::DataMember(ref data) => { - self.has_type_parameter_in_array.contains(&data.ty().into()) - } + Field::DataMember(ref data) => self + .has_type_parameter_in_array + .contains(&data.ty().into()), Field::Bitfields(..) => false, }); if fields_have { @@ -212,18 +200,18 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { if args_have { trace!( " template args have array, so \ - insantiation also has array" + instantiation also has array" ); return self.insert(id); } - let def_has = self.has_type_parameter_in_array.contains( - &template.template_definition().into(), - ); + let def_has = self + .has_type_parameter_in_array + .contains(&template.template_definition().into()); if def_has { trace!( " template definition has array, so \ - insantiation also has" + instantiation also has" ); return self.insert(id); } @@ -240,7 +228,7 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { { if let Some(edges) = self.dependencies.get(&id) { for item in edges { - trace!("enqueue {:?} into worklist", item); + trace!("enqueue {item:?} into worklist"); f(*item); } } diff --git a/bindgen/ir/analysis/has_vtable.rs b/bindgen/ir/analysis/has_vtable.rs new file mode 100644 index 0000000000..b8ecc6088e --- /dev/null +++ b/bindgen/ir/analysis/has_vtable.rs @@ -0,0 +1,234 @@ +//! Determining which types has vtable + +use super::{generate_dependencies, ConstrainResult, MonotoneFramework}; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::traversal::EdgeKind; +use crate::ir::ty::TypeKind; +use crate::{Entry, HashMap}; +use std::cmp; +use std::ops; + +/// The result of the `HasVtableAnalysis` for an individual item. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] +pub(crate) enum HasVtableResult { + /// The item does not have a vtable pointer. + #[default] + No, + + /// The item has a vtable and the actual vtable pointer is within this item. + SelfHasVtable, + + /// The item has a vtable, but the actual vtable pointer is in a base + /// member. + BaseHasVtable, +} + +impl HasVtableResult { + /// Take the least upper bound of `self` and `rhs`. + pub(crate) fn join(self, rhs: Self) -> Self { + cmp::max(self, rhs) + } +} + +impl ops::BitOr for HasVtableResult { + type Output = Self; + + fn bitor(self, rhs: HasVtableResult) -> Self::Output { + self.join(rhs) + } +} + +impl ops::BitOrAssign for HasVtableResult { + fn bitor_assign(&mut self, rhs: HasVtableResult) { + *self = self.join(rhs); + } +} + +/// An analysis that finds for each IR item whether it has vtable or not +/// +/// We use the monotone function `has vtable`, defined as follows: +/// +/// * If T is a type alias, a templated alias, an indirection to another type, +/// or a reference of a type, T has vtable if the type T refers to has vtable. +/// * If T is a compound type, T has vtable if we saw a virtual function when +/// parsing it or any of its base member has vtable. +/// * If T is an instantiation of an abstract template definition, T has +/// vtable if template definition has vtable +#[derive(Debug, Clone)] +pub(crate) struct HasVtableAnalysis<'ctx> { + ctx: &'ctx BindgenContext, + + // The incremental result of this analysis's computation. Everything in this + // set definitely has a vtable. + have_vtable: HashMap, + + // Dependencies saying that if a key ItemId has been inserted into the + // `have_vtable` set, then each of the ids in Vec need to be + // considered again. + // + // This is a subset of the natural IR graph with reversed edges, where we + // only include the edges from the IR graph that can affect whether a type + // has a vtable or not. + dependencies: HashMap>, +} + +impl HasVtableAnalysis<'_> { + fn consider_edge(kind: EdgeKind) -> bool { + // These are the only edges that can affect whether a type has a + // vtable or not. + matches!( + kind, + EdgeKind::TypeReference | + EdgeKind::BaseMember | + EdgeKind::TemplateDeclaration + ) + } + + fn insert>( + &mut self, + id: Id, + result: HasVtableResult, + ) -> ConstrainResult { + if let HasVtableResult::No = result { + return ConstrainResult::Same; + } + + let id = id.into(); + match self.have_vtable.entry(id) { + Entry::Occupied(mut entry) => { + if *entry.get() < result { + entry.insert(result); + ConstrainResult::Changed + } else { + ConstrainResult::Same + } + } + Entry::Vacant(entry) => { + entry.insert(result); + ConstrainResult::Changed + } + } + } + + fn forward(&mut self, from: Id1, to: Id2) -> ConstrainResult + where + Id1: Into, + Id2: Into, + { + let from = from.into(); + let to = to.into(); + + match self.have_vtable.get(&from) { + None => ConstrainResult::Same, + Some(r) => self.insert(to, *r), + } + } +} + +impl<'ctx> MonotoneFramework for HasVtableAnalysis<'ctx> { + type Node = ItemId; + type Extra = &'ctx BindgenContext; + type Output = HashMap; + + fn new(ctx: &'ctx BindgenContext) -> HasVtableAnalysis<'ctx> { + let have_vtable = HashMap::default(); + let dependencies = generate_dependencies(ctx, Self::consider_edge); + + HasVtableAnalysis { + ctx, + have_vtable, + dependencies, + } + } + + fn initial_worklist(&self) -> Vec { + self.ctx.allowlisted_items().iter().copied().collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + trace!("constrain {id:?}"); + + let item = self.ctx.resolve_item(id); + let Some(ty) = item.as_type() else { + return ConstrainResult::Same; + }; + + // TODO #851: figure out a way to handle deriving from template type parameters. + match *ty.kind() { + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::ResolvedTypeRef(t) | + TypeKind::Reference(t) => { + trace!( + " aliases and references forward to their inner type" + ); + self.forward(t, id) + } + + TypeKind::Comp(ref info) => { + trace!(" comp considers its own methods and bases"); + let mut result = HasVtableResult::No; + + if info.has_own_virtual_method() { + trace!(" comp has its own virtual method"); + result |= HasVtableResult::SelfHasVtable; + } + + let bases_has_vtable = info.base_members().iter().any(|base| { + trace!(" comp has a base with a vtable: {base:?}"); + self.have_vtable.contains_key(&base.ty.into()) + }); + if bases_has_vtable { + result |= HasVtableResult::BaseHasVtable; + } + + self.insert(id, result) + } + + TypeKind::TemplateInstantiation(ref inst) => { + self.forward(inst.template_definition(), id) + } + + _ => ConstrainResult::Same, + } + } + + fn each_depending_on(&self, id: ItemId, mut f: F) + where + F: FnMut(ItemId), + { + if let Some(edges) = self.dependencies.get(&id) { + for item in edges { + trace!("enqueue {item:?} into worklist"); + f(*item); + } + } + } +} + +impl<'ctx> From> for HashMap { + fn from(analysis: HasVtableAnalysis<'ctx>) -> Self { + // We let the lack of an entry mean "No" to save space. + extra_assert!(analysis + .have_vtable + .values() + .all(|v| { *v != HasVtableResult::No })); + + analysis.have_vtable + } +} + +/// A convenience trait for the things for which we might wonder if they have a +/// vtable during codegen. +/// +/// This is not for _computing_ whether the thing has a vtable, it is for +/// looking up the results of the `HasVtableAnalysis`'s computations for a +/// specific thing. +pub(crate) trait HasVtable { + /// Return `true` if this thing has vtable, `false` otherwise. + fn has_vtable(&self, ctx: &BindgenContext) -> bool; + + /// Return `true` if this thing has an actual vtable pointer in itself, as + /// opposed to transitively in a base member. + fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool; +} diff --git a/bindgen/ir/analysis/mod.rs b/bindgen/ir/analysis/mod.rs new file mode 100644 index 0000000000..74a305edfb --- /dev/null +++ b/bindgen/ir/analysis/mod.rs @@ -0,0 +1,395 @@ +//! Fix-point analyses on the IR using the "monotone framework". +//! +//! A lattice is a set with a partial ordering between elements, where there is +//! a single least upper bound and a single greatest least bound for every +//! subset. We are dealing with finite lattices, which means that it has a +//! finite number of elements, and it follows that there exists a single top and +//! a single bottom member of the lattice. For example, the power set of a +//! finite set forms a finite lattice where partial ordering is defined by set +//! inclusion, that is `a <= b` if `a` is a subset of `b`. Here is the finite +//! lattice constructed from the set {0,1,2}: +//! +//! ```text +//! .----- Top = {0,1,2} -----. +//! / | \ +//! / | \ +//! / | \ +//! {0,1} -------. {0,2} .--------- {1,2} +//! | \ / \ / | +//! | / \ | +//! | / \ / \ | +//! {0} --------' {1} `---------- {2} +//! \ | / +//! \ | / +//! \ | / +//! `------ Bottom = {} ------' +//! ``` +//! +//! A monotone function `f` is a function where if `x <= y`, then it holds that +//! `f(x) <= f(y)`. It should be clear that running a monotone function to a +//! fix-point on a finite lattice will always terminate: `f` can only "move" +//! along the lattice in a single direction, and therefore can only either find +//! a fix-point in the middle of the lattice or continue to the top or bottom +//! depending if it is ascending or descending the lattice respectively. +//! +//! For a deeper introduction to the general form of this kind of analysis, see +//! [Static Program Analysis by Anders Møller and Michael I. Schwartzbach][spa]. +//! +//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf + +// Re-export individual analyses. +mod template_params; +pub(crate) use self::template_params::UsedTemplateParameters; +mod derive; +pub use self::derive::DeriveTrait; +pub(crate) use self::derive::{as_cannot_derive_set, CannotDerive}; +mod has_vtable; +pub(crate) use self::has_vtable::{ + HasVtable, HasVtableAnalysis, HasVtableResult, +}; +mod has_destructor; +pub(crate) use self::has_destructor::HasDestructorAnalysis; +mod has_type_param_in_array; +pub(crate) use self::has_type_param_in_array::HasTypeParameterInArray; +mod has_float; +pub(crate) use self::has_float::HasFloat; +mod sizedness; +pub(crate) use self::sizedness::{ + Sizedness, SizednessAnalysis, SizednessResult, +}; + +use crate::ir::context::{BindgenContext, ItemId}; + +use crate::ir::traversal::{EdgeKind, Trace}; +use crate::HashMap; +use std::fmt; +use std::ops; + +/// An analysis in the monotone framework. +/// +/// Implementors of this trait must maintain the following two invariants: +/// +/// 1. The concrete data must be a member of a finite-height lattice. +/// 2. The concrete `constrain` method must be monotone: that is, +/// if `x <= y`, then `constrain(x) <= constrain(y)`. +/// +/// If these invariants do not hold, iteration to a fix-point might never +/// complete. +/// +/// For a simple example analysis, see the `ReachableFrom` type in the `tests` +/// module below. +pub(crate) trait MonotoneFramework: Sized + fmt::Debug { + /// The type of node in our dependency graph. + /// + /// This is just generic (and not `ItemId`) so that we can easily unit test + /// without constructing real `Item`s and their `ItemId`s. + type Node: Copy; + + /// Any extra data that is needed during computation. + /// + /// Again, this is just generic (and not `&BindgenContext`) so that we can + /// easily unit test without constructing real `BindgenContext`s full of + /// real `Item`s and real `ItemId`s. + type Extra: Sized; + + /// The final output of this analysis. Once we have reached a fix-point, we + /// convert `self` into this type, and return it as the final result of the + /// analysis. + type Output: From + fmt::Debug; + + /// Construct a new instance of this analysis. + fn new(extra: Self::Extra) -> Self; + + /// Get the initial set of nodes from which to start the analysis. Unless + /// you are sure of some domain-specific knowledge, this should be the + /// complete set of nodes. + fn initial_worklist(&self) -> Vec; + + /// Update the analysis for the given node. + /// + /// If this results in changing our internal state (ie, we discovered that + /// we have not reached a fix-point and iteration should continue), return + /// `ConstrainResult::Changed`. Otherwise, return `ConstrainResult::Same`. + /// When `constrain` returns `ConstrainResult::Same` for all nodes in the + /// set, we have reached a fix-point and the analysis is complete. + fn constrain(&mut self, node: Self::Node) -> ConstrainResult; + + /// For each node `d` that depends on the given `node`'s current answer when + /// running `constrain(d)`, call `f(d)`. This informs us which new nodes to + /// queue up in the worklist when `constrain(node)` reports updated + /// information. + fn each_depending_on(&self, node: Self::Node, f: F) + where + F: FnMut(Self::Node); +} + +/// Whether an analysis's `constrain` function modified the incremental results +/// or not. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub(crate) enum ConstrainResult { + /// The incremental results were updated, and the fix-point computation + /// should continue. + Changed, + + /// The incremental results were not updated. + #[default] + Same, +} + +impl ops::BitOr for ConstrainResult { + type Output = Self; + + fn bitor(self, rhs: ConstrainResult) -> Self::Output { + if self == ConstrainResult::Changed || rhs == ConstrainResult::Changed { + ConstrainResult::Changed + } else { + ConstrainResult::Same + } + } +} + +impl ops::BitOrAssign for ConstrainResult { + fn bitor_assign(&mut self, rhs: ConstrainResult) { + *self = *self | rhs; + } +} + +/// Run an analysis in the monotone framework. +pub(crate) fn analyze(extra: Analysis::Extra) -> Analysis::Output +where + Analysis: MonotoneFramework, +{ + let mut analysis = Analysis::new(extra); + let mut worklist = analysis.initial_worklist(); + + while let Some(node) = worklist.pop() { + if let ConstrainResult::Changed = analysis.constrain(node) { + analysis.each_depending_on(node, |needs_work| { + worklist.push(needs_work); + }); + } + } + + analysis.into() +} + +/// Generate the dependency map for analysis +pub(crate) fn generate_dependencies( + ctx: &BindgenContext, + consider_edge: F, +) -> HashMap> +where + F: Fn(EdgeKind) -> bool, +{ + let mut dependencies = HashMap::default(); + + for &item in ctx.allowlisted_items() { + dependencies.entry(item).or_insert_with(Vec::new); + + { + // We reverse our natural IR graph edges to find dependencies + // between nodes. + item.trace( + ctx, + &mut |sub_item: ItemId, edge_kind| { + if ctx.allowlisted_items().contains(&sub_item) && + consider_edge(edge_kind) + { + dependencies + .entry(sub_item) + .or_insert_with(Vec::new) + .push(item); + } + }, + &(), + ); + } + } + dependencies +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::HashSet; + + // Here we find the set of nodes that are reachable from any given + // node. This is a lattice mapping nodes to subsets of all nodes. Our join + // function is set union. + // + // This is our test graph: + // + // +---+ +---+ + // | | | | + // | 1 | .----| 2 | + // | | | | | + // +---+ | +---+ + // | | ^ + // | | | + // | +---+ '------' + // '----->| | + // | 3 | + // .------| |------. + // | +---+ | + // | ^ | + // v | v + // +---+ | +---+ +---+ + // | | | | | | | + // | 4 | | | 5 |--->| 6 | + // | | | | | | | + // +---+ | +---+ +---+ + // | | | | + // | | | v + // | +---+ | +---+ + // | | | | | | + // '----->| 7 |<-----' | 8 | + // | | | | + // +---+ +---+ + // + // And here is the mapping from a node to the set of nodes that are + // reachable from it within the test graph: + // + // 1: {3,4,5,6,7,8} + // 2: {2} + // 3: {3,4,5,6,7,8} + // 4: {3,4,5,6,7,8} + // 5: {3,4,5,6,7,8} + // 6: {8} + // 7: {3,4,5,6,7,8} + // 8: {} + + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] + struct Node(usize); + + #[derive(Clone, Debug, Default, PartialEq, Eq)] + struct Graph(HashMap>); + + impl Graph { + fn make_test_graph() -> Graph { + let mut g = Graph::default(); + g.0.insert(Node(1), vec![Node(3)]); + g.0.insert(Node(2), vec![Node(2)]); + g.0.insert(Node(3), vec![Node(4), Node(5)]); + g.0.insert(Node(4), vec![Node(7)]); + g.0.insert(Node(5), vec![Node(6), Node(7)]); + g.0.insert(Node(6), vec![Node(8)]); + g.0.insert(Node(7), vec![Node(3)]); + g.0.insert(Node(8), vec![]); + g + } + + fn reverse(&self) -> Graph { + let mut reversed = Graph::default(); + for (node, edges) in &self.0 { + reversed.0.entry(*node).or_insert_with(Vec::new); + for referent in edges { + reversed + .0 + .entry(*referent) + .or_insert_with(Vec::new) + .push(*node); + } + } + reversed + } + } + + #[derive(Clone, Debug, PartialEq, Eq)] + struct ReachableFrom<'a> { + reachable: HashMap>, + graph: &'a Graph, + reversed: Graph, + } + + impl<'a> MonotoneFramework for ReachableFrom<'a> { + type Node = Node; + type Extra = &'a Graph; + type Output = HashMap>; + + fn new(graph: &'a Graph) -> Self { + let reversed = graph.reverse(); + ReachableFrom { + reachable: Default::default(), + graph, + reversed, + } + } + + fn initial_worklist(&self) -> Vec { + self.graph.0.keys().copied().collect() + } + + fn constrain(&mut self, node: Node) -> ConstrainResult { + // The set of nodes reachable from a node `x` is + // + // reachable(x) = s_0 U s_1 U ... U reachable(s_0) U reachable(s_1) U ... + // + // where there exist edges from `x` to each of `s_0, s_1, ...`. + // + // Yes, what follows is a **terribly** inefficient set union + // implementation. Don't copy this code outside of this test! + + let original_size = self.reachable.entry(node).or_default().len(); + + for sub_node in &self.graph.0[&node] { + self.reachable.get_mut(&node).unwrap().insert(*sub_node); + + let sub_reachable = + self.reachable.entry(*sub_node).or_default().clone(); + + for transitive in sub_reachable { + self.reachable.get_mut(&node).unwrap().insert(transitive); + } + } + + let new_size = self.reachable[&node].len(); + if original_size == new_size { + ConstrainResult::Same + } else { + ConstrainResult::Changed + } + } + + fn each_depending_on(&self, node: Node, mut f: F) + where + F: FnMut(Node), + { + for dep in &self.reversed.0[&node] { + f(*dep); + } + } + } + + impl<'a> From> for HashMap> { + fn from(reachable: ReachableFrom<'a>) -> Self { + reachable.reachable + } + } + + #[test] + fn monotone() { + let g = Graph::make_test_graph(); + let reachable = analyze::(&g); + println!("reachable = {reachable:#?}"); + + fn nodes(nodes: A) -> HashSet + where + A: AsRef<[usize]>, + { + nodes.as_ref().iter().copied().map(Node).collect() + } + + let mut expected = HashMap::default(); + expected.insert(Node(1), nodes([3, 4, 5, 6, 7, 8])); + expected.insert(Node(2), nodes([2])); + expected.insert(Node(3), nodes([3, 4, 5, 6, 7, 8])); + expected.insert(Node(4), nodes([3, 4, 5, 6, 7, 8])); + expected.insert(Node(5), nodes([3, 4, 5, 6, 7, 8])); + expected.insert(Node(6), nodes([8])); + expected.insert(Node(7), nodes([3, 4, 5, 6, 7, 8])); + expected.insert(Node(8), nodes([])); + println!("expected = {expected:#?}"); + + assert_eq!(reachable, expected); + } +} diff --git a/bindgen/ir/analysis/sizedness.rs b/bindgen/ir/analysis/sizedness.rs new file mode 100644 index 0000000000..ce3c2c3da1 --- /dev/null +++ b/bindgen/ir/analysis/sizedness.rs @@ -0,0 +1,353 @@ +//! Determining the sizedness of types (as base classes and otherwise). + +use super::{ + generate_dependencies, ConstrainResult, HasVtable, MonotoneFramework, +}; +use crate::ir::context::{BindgenContext, TypeId}; +use crate::ir::item::IsOpaque; +use crate::ir::traversal::EdgeKind; +use crate::ir::ty::TypeKind; +use crate::{Entry, HashMap}; +use std::{cmp, ops}; + +/// The result of the `Sizedness` analysis for an individual item. +/// +/// This is a chain lattice of the form: +/// +/// ```ignore +/// NonZeroSized +/// | +/// DependsOnTypeParam +/// | +/// ZeroSized +/// ``` +/// +/// We initially assume that all types are `ZeroSized` and then update our +/// understanding as we learn more about each type. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] +pub(crate) enum SizednessResult { + /// The type is zero-sized. + /// + /// This means that if it is a C++ type, and is not being used as a base + /// member, then we must add an `_address` byte to enforce the + /// unique-address-per-distinct-object-instance rule. + #[default] + ZeroSized, + + /// Whether this type is zero-sized or not depends on whether a type + /// parameter is zero-sized or not. + /// + /// For example, given these definitions: + /// + /// ```c++ + /// template + /// class Flongo : public T {}; + /// + /// class Empty {}; + /// + /// class NonEmpty { int x; }; + /// ``` + /// + /// Then `Flongo` is zero-sized, and needs an `_address` byte + /// inserted, while `Flongo` is *not* zero-sized, and should *not* + /// have an `_address` byte inserted. + /// + /// We don't properly handle this situation correctly right now: + /// + DependsOnTypeParam, + + /// Has some size that is known to be greater than zero. That doesn't mean + /// it has a static size, but it is not zero sized for sure. In other words, + /// it might contain an incomplete array or some other dynamically sized + /// type. + NonZeroSized, +} + +impl SizednessResult { + /// Take the least upper bound of `self` and `rhs`. + pub(crate) fn join(self, rhs: Self) -> Self { + cmp::max(self, rhs) + } +} + +impl ops::BitOr for SizednessResult { + type Output = Self; + + fn bitor(self, rhs: SizednessResult) -> Self::Output { + self.join(rhs) + } +} + +impl ops::BitOrAssign for SizednessResult { + fn bitor_assign(&mut self, rhs: SizednessResult) { + *self = self.join(rhs); + } +} + +/// An analysis that computes the sizedness of all types. +/// +/// * For types with known sizes -- for example pointers, scalars, etc... -- +/// they are assigned `NonZeroSized`. +/// +/// * For compound structure types with one or more fields, they are assigned +/// `NonZeroSized`. +/// +/// * For compound structure types without any fields, the results of the bases +/// are `join`ed. +/// +/// * For type parameters, `DependsOnTypeParam` is assigned. +#[derive(Debug)] +pub(crate) struct SizednessAnalysis<'ctx> { + ctx: &'ctx BindgenContext, + dependencies: HashMap>, + // Incremental results of the analysis. Missing entries are implicitly + // considered `ZeroSized`. + sized: HashMap, +} + +impl SizednessAnalysis<'_> { + fn consider_edge(kind: EdgeKind) -> bool { + // These are the only edges that can affect whether a type is + // zero-sized or not. + matches!( + kind, + EdgeKind::TemplateArgument | + EdgeKind::TemplateParameterDefinition | + EdgeKind::TemplateDeclaration | + EdgeKind::TypeReference | + EdgeKind::BaseMember | + EdgeKind::Field + ) + } + + /// Insert an incremental result, and return whether this updated our + /// knowledge of types and we should continue the analysis. + fn insert( + &mut self, + id: TypeId, + result: SizednessResult, + ) -> ConstrainResult { + trace!("inserting {result:?} for {id:?}"); + + if let SizednessResult::ZeroSized = result { + return ConstrainResult::Same; + } + + match self.sized.entry(id) { + Entry::Occupied(mut entry) => { + if *entry.get() < result { + entry.insert(result); + ConstrainResult::Changed + } else { + ConstrainResult::Same + } + } + Entry::Vacant(entry) => { + entry.insert(result); + ConstrainResult::Changed + } + } + } + + fn forward(&mut self, from: TypeId, to: TypeId) -> ConstrainResult { + match self.sized.get(&from) { + None => ConstrainResult::Same, + Some(r) => self.insert(to, *r), + } + } +} + +impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> { + type Node = TypeId; + type Extra = &'ctx BindgenContext; + type Output = HashMap; + + fn new(ctx: &'ctx BindgenContext) -> SizednessAnalysis<'ctx> { + let dependencies = generate_dependencies(ctx, Self::consider_edge) + .into_iter() + .filter_map(|(id, sub_ids)| { + id.as_type_id(ctx).map(|id| { + ( + id, + sub_ids + .into_iter() + .filter_map(|s| s.as_type_id(ctx)) + .collect::>(), + ) + }) + }) + .collect(); + + let sized = HashMap::default(); + + SizednessAnalysis { + ctx, + dependencies, + sized, + } + } + + fn initial_worklist(&self) -> Vec { + self.ctx + .allowlisted_items() + .iter() + .filter_map(|id| id.as_type_id(self.ctx)) + .collect() + } + + fn constrain(&mut self, id: TypeId) -> ConstrainResult { + trace!("constrain {id:?}"); + + if let Some(SizednessResult::NonZeroSized) = self.sized.get(&id) { + trace!(" already know it is not zero-sized"); + return ConstrainResult::Same; + } + + if id.has_vtable_ptr(self.ctx) { + trace!(" has an explicit vtable pointer, therefore is not zero-sized"); + return self.insert(id, SizednessResult::NonZeroSized); + } + + let ty = self.ctx.resolve_type(id); + + if id.is_opaque(self.ctx, &()) { + trace!(" type is opaque; checking layout..."); + let result = + ty.layout(self.ctx).map_or(SizednessResult::ZeroSized, |l| { + if l.size == 0 { + trace!(" ...layout has size == 0"); + SizednessResult::ZeroSized + } else { + trace!(" ...layout has size > 0"); + SizednessResult::NonZeroSized + } + }); + return self.insert(id, result); + } + + match *ty.kind() { + TypeKind::Void => { + trace!(" void is zero-sized"); + self.insert(id, SizednessResult::ZeroSized) + } + + TypeKind::TypeParam => { + trace!( + " type params sizedness depends on what they're \ + instantiated as" + ); + self.insert(id, SizednessResult::DependsOnTypeParam) + } + + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::NullPtr | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::Pointer(..) => { + trace!(" {:?} is known not to be zero-sized", ty.kind()); + self.insert(id, SizednessResult::NonZeroSized) + } + + TypeKind::ObjCInterface(..) => { + trace!(" obj-c interfaces always have at least the `isa` pointer"); + self.insert(id, SizednessResult::NonZeroSized) + } + + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::BlockPointer(t) | + TypeKind::ResolvedTypeRef(t) => { + trace!(" aliases and type refs forward to their inner type"); + self.forward(t, id) + } + + TypeKind::TemplateInstantiation(ref inst) => { + trace!( + " template instantiations are zero-sized if their \ + definition is zero-sized" + ); + self.forward(inst.template_definition(), id) + } + + TypeKind::Array(_, 0) => { + trace!(" arrays of zero elements are zero-sized"); + self.insert(id, SizednessResult::ZeroSized) + } + TypeKind::Array(..) => { + trace!(" arrays of > 0 elements are not zero-sized"); + self.insert(id, SizednessResult::NonZeroSized) + } + TypeKind::Vector(..) => { + trace!(" vectors are not zero-sized"); + self.insert(id, SizednessResult::NonZeroSized) + } + + TypeKind::Comp(ref info) => { + trace!(" comp considers its own fields and bases"); + + if !info.fields().is_empty() { + return self.insert(id, SizednessResult::NonZeroSized); + } + + let result = info + .base_members() + .iter() + .filter_map(|base| self.sized.get(&base.ty)) + .fold(SizednessResult::ZeroSized, |a, b| a.join(*b)); + + self.insert(id, result) + } + + TypeKind::Opaque => { + unreachable!("covered by the .is_opaque() check above") + } + + TypeKind::UnresolvedTypeRef(..) => { + unreachable!("Should have been resolved after parsing!"); + } + } + } + + fn each_depending_on(&self, id: TypeId, mut f: F) + where + F: FnMut(TypeId), + { + if let Some(edges) = self.dependencies.get(&id) { + for ty in edges { + trace!("enqueue {ty:?} into worklist"); + f(*ty); + } + } + } +} + +impl<'ctx> From> for HashMap { + fn from(analysis: SizednessAnalysis<'ctx>) -> Self { + // We let the lack of an entry mean "ZeroSized" to save space. + extra_assert!(analysis + .sized + .values() + .all(|v| { *v != SizednessResult::ZeroSized })); + + analysis.sized + } +} + +/// A convenience trait for querying whether some type or ID is sized. +/// +/// This is not for _computing_ whether the thing is sized, it is for looking up +/// the results of the `Sizedness` analysis's computations for a specific thing. +pub(crate) trait Sizedness { + /// Get the sizedness of this type. + fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult; + + /// Is the sizedness for this type `SizednessResult::ZeroSized`? + fn is_zero_sized(&self, ctx: &BindgenContext) -> bool { + self.sizedness(ctx) == SizednessResult::ZeroSized + } +} diff --git a/bindgen/ir/analysis/template_params.rs b/bindgen/ir/analysis/template_params.rs new file mode 100644 index 0000000000..df8f861cfe --- /dev/null +++ b/bindgen/ir/analysis/template_params.rs @@ -0,0 +1,601 @@ +//! Discover which template type parameters are actually used. +//! +//! ### Why do we care? +//! +//! C++ allows ignoring template parameters, while Rust does not. Usually we can +//! blindly stick a `PhantomData` inside a generic Rust struct to make up for +//! this. That doesn't work for templated type aliases, however: +//! +//! ```C++ +//! template +//! using Fml = int; +//! ``` +//! +//! If we generate the naive Rust code for this alias, we get: +//! +//! ```ignore +//! pub(crate) type Fml = ::std::os::raw::int; +//! ``` +//! +//! And this is rejected by `rustc` due to the unused type parameter. +//! +//! (Aside: in these simple cases, `libclang` will often just give us the +//! aliased type directly, and we will never even know we were dealing with +//! aliases, let alone templated aliases. It's the more convoluted scenarios +//! where we get to have some fun...) +//! +//! For such problematic template aliases, we could generate a tuple whose +//! second member is a `PhantomData`. Or, if we wanted to go the extra mile, +//! we could even generate some smarter wrapper that implements `Deref`, +//! `DerefMut`, `From`, `Into`, `AsRef`, and `AsMut` to the actually aliased +//! type. However, this is still lackluster: +//! +//! 1. Even with a billion conversion-trait implementations, using the generated +//! bindings is rather un-ergonomic. +//! 2. With either of these solutions, we need to keep track of which aliases +//! we've transformed like this in order to generate correct uses of the +//! wrapped type. +//! +//! Given that we have to properly track which template parameters ended up used +//! for (2), we might as well leverage that information to make ergonomic +//! bindings that don't contain any unused type parameters at all, and +//! completely avoid the pain of (1). +//! +//! ### How do we determine which template parameters are used? +//! +//! Determining which template parameters are actually used is a trickier +//! problem than it might seem at a glance. On the one hand, trivial uses are +//! easy to detect: +//! +//! ```C++ +//! template +//! class Foo { +//! T trivial_use_of_t; +//! }; +//! ``` +//! +//! It gets harder when determining if one template parameter is used depends on +//! determining if another template parameter is used. In this example, whether +//! `U` is used depends on whether `T` is used. +//! +//! ```C++ +//! template +//! class DoesntUseT { +//! int x; +//! }; +//! +//! template +//! class Fml { +//! DoesntUseT lololol; +//! }; +//! ``` +//! +//! We can express the set of used template parameters as a constraint solving +//! problem (where the set of template parameters used by a given IR item is the +//! union of its sub-item's used template parameters) and iterate to a +//! fixed-point. +//! +//! We use the `ir::analysis::MonotoneFramework` infrastructure for this +//! fix-point analysis, where our lattice is the mapping from each IR item to +//! the powerset of the template parameters that appear in the input C++ header, +//! our join function is set union. The set of template parameters appearing in +//! the program is finite, as is the number of IR items. We start at our +//! lattice's bottom element: every item mapping to an empty set of template +//! parameters. Our analysis only adds members to each item's set of used +//! template parameters, never removes them, so it is monotone. Because our +//! lattice is finite and our constraint function is monotone, iteration to a +//! fix-point will terminate. +//! +//! See `src/ir/analysis.rs` for more. + +use super::{ConstrainResult, MonotoneFramework}; +use crate::ir::context::{BindgenContext, ItemId}; +use crate::ir::item::{Item, ItemSet}; +use crate::ir::template::{TemplateInstantiation, TemplateParameters}; +use crate::ir::traversal::{EdgeKind, Trace}; +use crate::ir::ty::TypeKind; +use crate::{HashMap, HashSet}; + +/// An analysis that finds for each IR item its set of template parameters that +/// it uses. +/// +/// We use the monotone constraint function `template_param_usage`, defined as +/// follows: +/// +/// * If `T` is a named template type parameter, it trivially uses itself: +/// +/// ```ignore +/// template_param_usage(T) = { T } +/// ``` +/// +/// * If `inst` is a template instantiation, `inst.args` are the template +/// instantiation's template arguments, `inst.def` is the template definition +/// being instantiated, and `inst.def.params` is the template definition's +/// template parameters, then the instantiation's usage is the union of each +/// of its arguments' usages *if* the corresponding template parameter is in +/// turn used by the template definition: +/// +/// ```ignore +/// template_param_usage(inst) = union( +/// template_param_usage(inst.args[i]) +/// for i in 0..length(inst.args.length) +/// if inst.def.params[i] in template_param_usage(inst.def) +/// ) +/// ``` +/// +/// * Finally, for all other IR item kinds, we use our lattice's `join` +/// operation: set union with each successor of the given item's template +/// parameter usage: +/// +/// ```ignore +/// template_param_usage(v) = +/// union(template_param_usage(w) for w in successors(v)) +/// ``` +/// +/// Note that we ignore certain edges in the graph, such as edges from a +/// template declaration to its template parameters' definitions for this +/// analysis. If we didn't, then we would mistakenly determine that ever +/// template parameter is always used. +/// +/// The final wrinkle is handling of blocklisted types. Normally, we say that +/// the set of allowlisted items is the transitive closure of items explicitly +/// called out for allowlisting, *without* any items explicitly called out as +/// blocklisted. However, for the purposes of this analysis's correctness, we +/// simplify and consider run the analysis on the full transitive closure of +/// allowlisted items. We do, however, treat instantiations of blocklisted items +/// specially; see `constrain_instantiation_of_blocklisted_template` and its +/// documentation for details. +#[derive(Debug, Clone)] +pub(crate) struct UsedTemplateParameters<'ctx> { + ctx: &'ctx BindgenContext, + + // The Option is only there for temporary moves out of the hash map. See the + // comments in `UsedTemplateParameters::constrain` below. + used: HashMap>, + + dependencies: HashMap>, + + // The set of allowlisted items, without any blocklisted items reachable + // from the allowlisted items which would otherwise be considered + // allowlisted as well. + allowlisted_items: HashSet, +} + +impl UsedTemplateParameters<'_> { + fn consider_edge(kind: EdgeKind) -> bool { + match kind { + // For each of these kinds of edges, if the referent uses a template + // parameter, then it should be considered that the origin of the + // edge also uses the template parameter. + EdgeKind::TemplateArgument | + EdgeKind::BaseMember | + EdgeKind::Field | + EdgeKind::Constructor | + EdgeKind::Destructor | + EdgeKind::VarType | + EdgeKind::FunctionReturn | + EdgeKind::FunctionParameter | + EdgeKind::TypeReference => true, + + // An inner var or type using a template parameter is orthogonal + // from whether we use it. See template-param-usage-{6,11}.hpp. + EdgeKind::InnerVar | EdgeKind::InnerType => false, + + // We can't emit machine code for new monomorphizations of class + // templates' methods (and don't detect explicit instantiations) so + // we must ignore template parameters that are only used by + // methods. This doesn't apply to a function type's return or + // parameter types, however, because of type aliases of function + // pointers that use template parameters, eg + // tests/headers/struct_with_typedef_template_arg.hpp + EdgeKind::Method => false, + + // If we considered these edges, we would end up mistakenly claiming + // that every template parameter always used. + EdgeKind::TemplateDeclaration | + EdgeKind::TemplateParameterDefinition => false, + + // Since we have to be careful about which edges we consider for + // this analysis to be correct, we ignore generic edges. We also + // avoid a `_` wild card to force authors of new edge kinds to + // determine whether they need to be considered by this analysis. + EdgeKind::Generic => false, + } + } + + fn take_this_id_usage_set>( + &mut self, + this_id: Id, + ) -> ItemSet { + let this_id = this_id.into(); + self.used + .get_mut(&this_id) + .expect( + "Should have a set of used template params for every item \ + id", + ) + .take() + .expect( + "Should maintain the invariant that all used template param \ + sets are `Some` upon entry of `constrain`", + ) + } + + /// We say that blocklisted items use all of their template parameters. The + /// blocklisted type is most likely implemented explicitly by the user, + /// since it won't be in the generated bindings, and we don't know exactly + /// what they'll to with template parameters, but we can push the issue down + /// the line to them. + fn constrain_instantiation_of_blocklisted_template( + &self, + this_id: ItemId, + used_by_this_id: &mut ItemSet, + instantiation: &TemplateInstantiation, + ) { + trace!( + " instantiation of blocklisted template, uses all template \ + arguments" + ); + + let args = instantiation + .template_arguments() + .iter() + .map(|a| { + a.into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(self.ctx) + .id() + }) + .filter(|a| *a != this_id) + .flat_map(|a| { + self.used + .get(&a) + .expect("Should have a used entry for the template arg") + .as_ref() + .expect( + "Because a != this_id, and all used template \ + param sets other than this_id's are `Some`, \ + a's used template param set should be `Some`", + ) + .iter() + }); + + used_by_this_id.extend(args); + } + + /// A template instantiation's concrete template argument is only used if + /// the template definition uses the corresponding template parameter. + fn constrain_instantiation( + &self, + this_id: ItemId, + used_by_this_id: &mut ItemSet, + instantiation: &TemplateInstantiation, + ) { + trace!(" template instantiation"); + + let decl = self.ctx.resolve_type(instantiation.template_definition()); + let args = instantiation.template_arguments(); + + let params = decl.self_template_params(self.ctx); + + debug_assert!(this_id != instantiation.template_definition()); + let used_by_def = self.used + .get(&instantiation.template_definition().into()) + .expect("Should have a used entry for instantiation's template definition") + .as_ref() + .expect("And it should be Some because only this_id's set is None, and an \ + instantiation's template definition should never be the \ + instantiation itself"); + + for (arg, param) in args.iter().zip(params.iter()) { + trace!( + " instantiation's argument {arg:?} is used if definition's \ + parameter {param:?} is used", + ); + + if used_by_def.contains(¶m.into()) { + trace!(" param is used by template definition"); + + let arg = arg + .into_resolver() + .through_type_refs() + .through_type_aliases() + .resolve(self.ctx) + .id(); + + if arg == this_id { + continue; + } + + let used_by_arg = self + .used + .get(&arg) + .expect("Should have a used entry for the template arg") + .as_ref() + .expect( + "Because arg != this_id, and all used template \ + param sets other than this_id's are `Some`, \ + arg's used template param set should be \ + `Some`", + ) + .iter(); + used_by_this_id.extend(used_by_arg); + } + } + } + + /// The join operation on our lattice: the set union of all of this ID's + /// successors. + fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) { + trace!(" other item: join with successors' usage"); + + item.trace( + self.ctx, + &mut |sub_id, edge_kind| { + // Ignore ourselves, since union with ourself is a + // no-op. Ignore edges that aren't relevant to the + // analysis. + if sub_id == item.id() || !Self::consider_edge(edge_kind) { + return; + } + + let used_by_sub_id = self + .used + .get(&sub_id) + .expect("Should have a used set for the sub_id successor") + .as_ref() + .expect( + "Because sub_id != id, and all used template \ + param sets other than id's are `Some`, \ + sub_id's used template param set should be \ + `Some`", + ) + .iter(); + + trace!( + " union with {sub_id:?}'s usage: {:?}", + used_by_sub_id.clone().collect::>() + ); + + used_by_this_id.extend(used_by_sub_id); + }, + &(), + ); + } +} + +impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { + type Node = ItemId; + type Extra = &'ctx BindgenContext; + type Output = HashMap; + + fn new(ctx: &'ctx BindgenContext) -> UsedTemplateParameters<'ctx> { + let mut used = HashMap::default(); + let mut dependencies = HashMap::default(); + let allowlisted_items: HashSet<_> = + ctx.allowlisted_items().iter().copied().collect(); + + let allowlisted_and_blocklisted_items: ItemSet = allowlisted_items + .iter() + .copied() + .flat_map(|i| { + let mut reachable = vec![i]; + i.trace( + ctx, + &mut |s, _| { + reachable.push(s); + }, + &(), + ); + reachable + }) + .collect(); + + for item in allowlisted_and_blocklisted_items { + dependencies.entry(item).or_insert_with(Vec::new); + used.entry(item).or_insert_with(|| Some(ItemSet::new())); + + { + // We reverse our natural IR graph edges to find dependencies + // between nodes. + item.trace( + ctx, + &mut |sub_item: ItemId, _| { + used.entry(sub_item) + .or_insert_with(|| Some(ItemSet::new())); + dependencies + .entry(sub_item) + .or_insert_with(Vec::new) + .push(item); + }, + &(), + ); + } + + // Additionally, whether a template instantiation's template + // arguments are used depends on whether the template declaration's + // generic template parameters are used. + let item_kind = + ctx.resolve_item(item).as_type().map(|ty| ty.kind()); + if let Some(TypeKind::TemplateInstantiation(inst)) = item_kind { + let decl = ctx.resolve_type(inst.template_definition()); + let args = inst.template_arguments(); + + // Although template definitions should always have + // template parameters, there is a single exception: + // opaque templates. Hence the unwrap_or. + let params = decl.self_template_params(ctx); + + for (arg, param) in args.iter().zip(params.iter()) { + let arg = arg + .into_resolver() + .through_type_aliases() + .through_type_refs() + .resolve(ctx) + .id(); + + let param = param + .into_resolver() + .through_type_aliases() + .through_type_refs() + .resolve(ctx) + .id(); + + used.entry(arg).or_insert_with(|| Some(ItemSet::new())); + used.entry(param).or_insert_with(|| Some(ItemSet::new())); + + dependencies + .entry(arg) + .or_insert_with(Vec::new) + .push(param); + } + } + } + + if cfg!(feature = "__testing_only_extra_assertions") { + // Invariant: The `used` map has an entry for every allowlisted + // item, as well as all explicitly blocklisted items that are + // reachable from allowlisted items. + // + // Invariant: the `dependencies` map has an entry for every + // allowlisted item. + // + // (This is so that every item we call `constrain` on is guaranteed + // to have a set of template parameters, and we can allow + // blocklisted templates to use all of their parameters). + for item in &allowlisted_items { + extra_assert!(used.contains_key(item)); + extra_assert!(dependencies.contains_key(item)); + item.trace( + ctx, + &mut |sub_item, _| { + extra_assert!(used.contains_key(&sub_item)); + extra_assert!(dependencies.contains_key(&sub_item)); + }, + &(), + ); + } + } + + UsedTemplateParameters { + ctx, + used, + dependencies, + allowlisted_items, + } + } + + fn initial_worklist(&self) -> Vec { + // The transitive closure of all allowlisted items, including explicitly + // blocklisted items. + self.ctx + .allowlisted_items() + .iter() + .copied() + .flat_map(|i| { + let mut reachable = vec![i]; + i.trace( + self.ctx, + &mut |s, _| { + reachable.push(s); + }, + &(), + ); + reachable + }) + .collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + // Invariant: all hash map entries' values are `Some` upon entering and + // exiting this method. + extra_assert!(self.used.values().all(|v| v.is_some())); + + // Take the set for this ID out of the hash map while we mutate it based + // on other hash map entries. We *must* put it back into the hash map at + // the end of this method. This allows us to side-step HashMap's lack of + // an analog to slice::split_at_mut. + let mut used_by_this_id = self.take_this_id_usage_set(id); + + trace!("constrain {id:?}"); + trace!(" initially, used set is {used_by_this_id:?}"); + + let original_len = used_by_this_id.len(); + + let item = self.ctx.resolve_item(id); + let ty_kind = item.as_type().map(|ty| ty.kind()); + match ty_kind { + // Named template type parameters trivially use themselves. + Some(&TypeKind::TypeParam) => { + trace!(" named type, trivially uses itself"); + used_by_this_id.insert(id); + } + // Template instantiations only use their template arguments if the + // template definition uses the corresponding template parameter. + Some(TypeKind::TemplateInstantiation(inst)) => { + if self + .allowlisted_items + .contains(&inst.template_definition().into()) + { + self.constrain_instantiation( + id, + &mut used_by_this_id, + inst, + ); + } else { + self.constrain_instantiation_of_blocklisted_template( + id, + &mut used_by_this_id, + inst, + ); + } + } + // Otherwise, add the union of each of its referent item's template + // parameter usage. + _ => self.constrain_join(&mut used_by_this_id, item), + } + + trace!(" finally, used set is {used_by_this_id:?}"); + + let new_len = used_by_this_id.len(); + assert!( + new_len >= original_len, + "This is the property that ensures this function is monotone -- \ + if it doesn't hold, the analysis might never terminate!" + ); + + // Put the set back in the hash map and restore our invariant. + debug_assert!(self.used[&id].is_none()); + self.used.insert(id, Some(used_by_this_id)); + extra_assert!(self.used.values().all(|v| v.is_some())); + + if new_len == original_len { + ConstrainResult::Same + } else { + ConstrainResult::Changed + } + } + + fn each_depending_on(&self, item: ItemId, mut f: F) + where + F: FnMut(ItemId), + { + if let Some(edges) = self.dependencies.get(&item) { + for item in edges { + trace!("enqueue {item:?} into worklist"); + f(*item); + } + } + } +} + +impl<'ctx> From> for HashMap { + fn from(used_templ_params: UsedTemplateParameters<'ctx>) -> Self { + used_templ_params + .used + .into_iter() + .map(|(k, v)| (k, v.unwrap())) + .collect() + } +} diff --git a/bindgen/ir/annotations.rs b/bindgen/ir/annotations.rs new file mode 100644 index 0000000000..7f5d74b3ee --- /dev/null +++ b/bindgen/ir/annotations.rs @@ -0,0 +1,259 @@ +//! Types and functions related to bindgen annotation comments. +//! +//! Users can add annotations in doc comments to types that they would like to +//! replace other types with, mark as opaque, etc. This module deals with all of +//! that stuff. + +use std::str::FromStr; + +use crate::clang; + +/// What kind of visibility modifier should be used for a struct or field? +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Default)] +pub enum FieldVisibilityKind { + /// Fields are marked as private, i.e., struct Foo {bar: bool} + Private, + /// Fields are marked as crate public, i.e., struct Foo {pub(crate) bar: bool} + PublicCrate, + /// Fields are marked as public, i.e., struct Foo {pub bar: bool} + #[default] + Public, +} + +impl FromStr for FieldVisibilityKind { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "private" => Ok(Self::Private), + "crate" => Ok(Self::PublicCrate), + "public" => Ok(Self::Public), + _ => Err(format!("Invalid visibility kind: `{s}`")), + } + } +} + +impl std::fmt::Display for FieldVisibilityKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + FieldVisibilityKind::Private => "private", + FieldVisibilityKind::PublicCrate => "crate", + FieldVisibilityKind::Public => "public", + }; + + s.fmt(f) + } +} + +/// What kind of accessor should we provide for a field? +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +pub(crate) enum FieldAccessorKind { + /// No accessor. + None, + /// Plain accessor. + Regular, + /// Unsafe accessor. + Unsafe, + /// Immutable accessor. + Immutable, +} + +/// Annotations for a given item, or a field. +/// +/// You can see the kind of comments that are accepted in the [Doxygen documentation](https://www.doxygen.nl/manual/docblocks.html). +#[derive(Default, Clone, PartialEq, Eq, Debug)] +pub(crate) struct Annotations { + /// Whether this item is marked as opaque. Only applies to types. + opaque: bool, + /// Whether this item should be hidden from the output. Only applies to + /// types, or enum variants. + hide: bool, + /// Whether this type should be replaced by another. The name is a + /// namespace-aware path. + use_instead_of: Option>, + /// Manually disable deriving copy/clone on this type. Only applies to + /// struct or union types. + disallow_copy: bool, + /// Manually disable deriving debug on this type. + disallow_debug: bool, + /// Manually disable deriving/implement default on this type. + disallow_default: bool, + /// Whether to add a `#[must_use]` annotation to this type. + must_use_type: bool, + /// Visibility of struct fields. You can set this on + /// structs (it will apply to all the fields), or individual fields. + visibility_kind: Option, + /// The kind of accessor this field will have. Also can be applied to + /// structs so all the fields inside share it by default. + accessor_kind: Option, + /// Whether this enum variant should be constified. + /// + /// This is controlled by the `constant` attribute, this way: + /// + /// ```cpp + /// enum Foo { + /// Bar = 0, /**<