Jul 11, 2019

[clang] Catching use-after-move bugs with Clang's consumed annotations

Reference:
https://awesomekling.github.io/Catching-use-after-move-bugs-with-Clang-consumed-annotations/

Clang9 Attributes:
https://clang.llvm.org/docs/AttributeReference.html#consumed-annotation-checking

The reason once we've defined destructor for our type compiler will not generate default move constructor/move assignment which ask the designer to explicit define those two member functions due to move semantic,  i.e what should the r-value object's data members being handled? If the data member is the resource owner , it should be nullptred(by move constructor/move assignment), which allows the type's destructor delete the nullptr(i.e a no-op).
However, if any member functions which deref the nullptred data member will crash the process at run-time.

Can this being caught at compile time in C++, like Rust did?
Clang provides “Consumed Annotation Checking

code example:
class [[clang::consumable(unconsumed)]] CleverObject {
public:
    CleverObject() {}
    CleverObject(CleverObject&& other) { other.invalidate(); }

    [[clang::callable_when(unconsumed)]]
    void do_something() { assert(m_valid); }

private:
    [[clang::set_typestate(consumed)]]
    void invalidate() { m_valid = false; }

    bool m_valid { true };
};

int main(int, char**)
{
    CleverObject object;
    auto other = std::move(object);
    object.do_something();
    return 0;
}
Realworld Usage:
https://github.com/SerenityOS/serenity/blob/master/AK/NonnullRefPtr.h

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.