Skip to content

noexcept not supported and can mess up subclasses #1435

Open
@SteffenLindner

Description

@SteffenLindner

Describe the bug
When defining a virtual noexcept method in a C++ class that is derived using #[subclass(superclass("MyCppClass"))], the generated wrapper methods do not include the noexcept statement, leading to a compiler error due to looser exception statement.

To Reproduce

// src/code.hpp
#pragma once
class SuperClass
{
public:
    virtual void doSomething() const noexcept = 0;
    virtual ~SuperClass() {};
};
// build.rs
fn main() -> miette::Result<()> {
    let mut b = autocxx_build::Builder::new("src/main.rs", &["./src"])
        .extra_clang_args(&["-std=c++17"])
        .auto_allowlist(true)
        .build()?;

    b.flag_if_supported("-std=c++17").compile("noexcept-test");
    println!("cargo:rerun-if-changed=src/main.rs");
    println!("cargo:rerun-if-changed=src/code.hpp");
    Ok(())
}
// src/main.rs
use autocxx::prelude::*;
use autocxx::subclass::prelude::*;
use ffi::SuperClass_methods;

include_cpp! {
    #include "code.hpp"
    safety!(unsafe) // unsafety policy; see docs
}

#[subclass(superclass("SuperClass"))]
#[derive(Default)]
pub struct DerivedStruct {}

impl ffi::SuperClass_methods for DerivedStruct {
    fn doSomething(&self) {
        println!("Do something");
    }
}

fn main() {
    let t = DerivedStruct::default_rust_owned();
    t.borrow().doSomething();
}

Expected behavior
Print statement is executed of doSomething call, which is done if the noexcept is removed from the virtual method.

Additional context
Error:

cargo:warning=In file included from /home/XXX/autocxx-bugs/noexcept/target/debug/build/noexcept-568b2dad4acfbf95/out/autocxx-build-dir/cxx/gen0.cxx:2: cargo:warning=/home/XXX/autocxx-bugs/noexcept/target/debug/build/noexcept-568b2dad4acfbf95/out/autocxx-build-dir/include/autocxxgen_ffi.h:41:6: error: looser exception specification on overriding virtual function 'virtual void DerivedStructCpp::doSomething() const' cargo:warning= 41 | void doSomething() const; cargo:warning= | ^~~~~~~~~~~ cargo:warning=In file included from /home/XXX/autocxx-bugs/noexcept/target/debug/build/noexcept-568b2dad4acfbf95/out/autocxx-build-dir/cxx/gen0.cxx:1: cargo:warning=./src/code.hpp:5:18: note: overridden function is 'virtual void SuperClass::doSomething() const noexcept' cargo:warning= 5 | virtual void doSomething() const noexcept = 0;

I belive it should be rather straightforward to also pass the noexcept to the generated code by autocxx / cxx.

In the generated C++ code, the noexcept is missing:

// XX//autocxxgen_ffi.h
struct DerivedStructHolder;
class DerivedStructCpp : public SuperClass
{
public:
inline  DerivedStructCpp(rust::Box<DerivedStructHolder> arg0) : obs(std::move(arg0)) {  }
void doSomething() const;
const SuperClass& As_SuperClass() const { return *this; }
SuperClass& As_SuperClass_mut() { return *this; }
void DerivedStructCpp_remove_ownership() const;
private:rust::Box<DerivedStructHolder> obs;
void really_remove_ownership();

};

Metadata

Metadata

Assignees

No one assigned

    Labels

    cpp-featureC++ feature not yet supported

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions