Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect use after move during compilation?

The clang-tidy static analyzer detects uses of variables after being moved.

class a_class {
    std::unique_ptr<int> p_;
 public:
    auto p() -> auto& {return p_;}
    void f() const {}
};

int main() {
    auto aa = a_class{};
    [[maybe_unused]] auto bb = std::move(aa);
    aa.f();
}
 error: Method called on moved-from object 'aa' [clang-analyzer-cplusplus.Move,-warnings-as-errors]

This great! ©.

How can I make the compiler, clang or GCC detect the same issue too? Either by activating some warning option or by some (non-standard?) attribute?

I tried using -Wmove in clang and the [[consumed]] attribute but they didn't help. Perhaps I used them incorrectly.

The code is here: https://godbolt.org/z/18hr4vn7x (the lower panel is clang-tidy and the mid panel on the right is the [empty] compiler output)

Is there a chance a compiler will warn about this or it is just too costly for the compiler to check for this pattern?

like image 839
alfC Avatar asked Jan 24 '26 04:01

alfC


2 Answers

I found one way to do it, using attributes in clang. . (A GCC or a more standard solution is still welcome.)

  1. needs clang 6 or higher
  2. mark the class as "consumable"
  3. mark the method(s) "callable-when-unconsumed" (not sure how to make this the default)
class [[clang::consumable(unconsumed)]] a_class {
    std::unique_ptr<int> p_;

public:
    [[clang::callable_when(unconsumed)]]
    void f() {}

    // private: [[clang::set_typestate(consumed)]] void invalidate() {}  // not needed but good to know
};

https://godbolt.org/z/45q8vzdnc

The recipe is simplified from https://awesomekling.github.io/Catching-use-after-move-bugs-with-Clang-consumed-annotations/ . I couldn't find detailed documentation on how to use the these features.

It is simplified because:

a) it seems that "clang-consumable" moved object becomes "consumed" by default when moved-from, so it is not necessary to write a special function to invalidate if not necessary (no need for [[clang::set_typestate(consumed)]]).

b) constructors seem to leave the object in an unconsumed state by default (no need for [[clang::return_typestate(unconsumed)]]);

like image 75
alfC Avatar answered Jan 25 '26 18:01

alfC


If a compiler isn't built with a setting to do this, then you can't make it do this. Use-after-move is a legitimate thing in C++, so no compiler is obligated to consider it an error.

These kinds of things are what static analyzers are for.

like image 32
Nicol Bolas Avatar answered Jan 25 '26 16:01

Nicol Bolas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!