rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

bindgen Incompatibility with LLVM 21.1 C++ Template Metaprogramming

Open chatgpt-copypasta opened this issue 4 months ago • 0 comments

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.

chatgpt-copypasta avatar Jul 29 '25 02:07 chatgpt-copypasta