Skip to content

bindgen Incompatibility with LLVM 21.1 C++ Template Metaprogramming #3256

@chatgpt-copypasta

Description

@chatgpt-copypasta

ISSUE

bindgen fails to parse LLVM 21's libc++ template metaprogramming, specifically std::basic_string_view and std::invoke_result_t templates, generating invalid Rust code.

EXPECTED BEHAVIOR

bindgen should handle LLVM 21's C++ standard library templates gracefully, either by parsing them correctly or providing better fallback mechanisms.

STEPS TO REPRODUCE

Environment:

  • LLVM 21.1.0-rc1
  • bindgen 0.72.0
  • macOS 15.5 aarch64
  • Large C++ codebase (Firefox) with complex template usage

Minimal Reproduction Case:

// test.hpp
#include <string_view>
#include <type_traits>

template<typename F, typename... Args>
using invoke_result_test = std::invoke_result_t<F, Args...>;

class TestClass {
public:
    std::string_view get_view() const;
    template<typename Func>
    auto call_func(Func f) -> std::invoke_result_t<Func>;
};

bindgen Command:

bindgen test.hpp --output test.rs -- -std=c++17 -I/opt/llvm-21.1.0-rc1/include/c++/v1

ATTEMPTS TO RESOLVE

1. Basic String View Template Issues
Generated Invalid Rust:

error[E0412]: cannot find type `_CharT` in this scope
error[E0412]: cannot find type `_Traits` in this scope
error[E0109]: type arguments are not allowed on builtin type `u8`

Working Fix - Template Blocking:

.blocklist_type(".*basic_string_view.*")
.opaque_type(".*basic_string_view.*")
.blocklist_type("std::.*basic_string_view.*") 
.opaque_type("std::.*basic_string_view.*")
.blocklist_type("std::__1::basic_string_view.*")
.opaque_type("std::__1::basic_string_view.*")

2. invoke_result_t Template Issues

Generated Invalid Rust:

error[E0412]: cannot find type `invoke_result_t` in module `root::std::__1`
     --> structs.rs:51072:29
      |
51072 |             root::std::__1::invoke_result_t<ResolveFunction, ResolveValueT>;
      |                             ^^^^^^^^^^^^^^^ not found in `root::std::__1`

Attempted Fix (Partial Success):

.blocklist_type(".*__invoke_result_t.*")
.opaque_type(".*__invoke_result_t.*")
.blocklist_type(".*invoke_result_t.*")
.opaque_type(".*invoke_result_t.*")

Result: Some instances blocked, but template still leaks through in complex instantiations.

OUTCOME AND FINDINGS

Root Cause Analysis

  1. Template Parameter Extraction: bindgen attempts to extract template parameters (_CharT, _Traits, _Args) but fails to resolve them in LLVM 21's more complex template definitions
  2. SFINAE Handling: LLVM 21 uses more sophisticated SFINAE patterns that bindgen's template parser cannot handle
  3. Namespace Resolution: Complex nested template instantiations in std::__1 namespace are not properly resolved

LLVM 21 Specific Changes
LLVM 21's libc++ appears to use more aggressive template metaprogramming:

// LLVM 21 style - more complex SFINAE
template<class _Fn, class... _Args>
using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;

// Earlier versions - simpler patterns  
template<class F, class... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;

Workaround Effectiveness

  • blocklist_type + opaque_type: Effective for simple cases
  • Regex patterns: Inconsistent - some template instantiations still leak through
  • Template recursion: Deep template hierarchies still cause issues

REQUESTED ACTION

Short Term

  1. Improve Template Blocking: Make blocklist_type patterns more aggressive at catching complex template instantiations
  2. Better Error Messages: When template parsing fails, provide clearer guidance on blocking problematic types
  3. Template Fallback: When complex templates can't be parsed, fall back to opaque types automatically

Long Term

  1. C++17/20 Template Support: Enhance parser to handle modern C++ template metaprogramming patterns
  2. SFINAE Recognition: Detect and gracefully handle SFINAE patterns that will never generate valid Rust
  3. Standard Library Profiles: Pre-configured blocklists for known problematic stdlib template patterns

Specific Technical Improvements

  1. Template Parameter Resolution: Fix handling of unresolved template parameters in complex instantiations
  2. Namespace Qualification: Improve resolution of deeply nested template types in std::__1
  3. Recursive Template Blocking: When a template is blocked, also block all its dependent instantiations

This affects any large C++ codebase attempting to use LLVM 21 with bindgen.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions