Home > Mobile >  Detect use after move during compilation?
Detect use after move during compilation?

Time:10-30

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?

CodePudding user response:

A GCC or simpler or more standard solutions are still welcome.


I found one way to do it, using attributes in clang.

  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 a consumed state by default (no need for [[clang::return_typestate(unconsumed)]]);

CodePudding user response:

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.

  • Related