Search code examples
c++clionstatic-analysisclang-tidystdoptional

How can I get clang-tidy to not complain about passing kind-of-lightweight types by value?


CLion (2023.1.2) is running clang-tidy v17 on a project of mine. It's complaining about me passing an std::experimental::optional (from C++14) by value instead of by reference. That seems egregious to me... how can I increase the "object weight threshold" for eliciting clang-tidy complaints about copying?

The exact problem description:

Clang-Tidy: The parameter 'whatever' is copied for each invocation but only used as a const reference; consider making it a const reference

Note: Unlike in this question, I want to change clang-tidy's threshold, not whitelist a specific line of code or specific type.


Solution

  • The clang-tidy check "performance-unnecessary-value-param" is looking for argument types that satisfy the "isExpensiveToCopy" predicate, which is a pretty simple test for non-trivial types:

      return !Type.isTriviallyCopyableType(Context) &&
             !classHasTrivialCopyAndDestroy(Type) &&
             !hasDeletedCopyConstructor(Type) &&
             !Type->isObjCLifetimeType();
    

    This is reasonable in your case, because the TS std::experimental::optional does not propagate trivial copyability from its parameter, whereas std::optional does:

    void f(std::optional<int>) {} // does not warn, because:
    static_assert(std::is_trivially_copyable_v<std::optional<int>>);
    
    void f(std::experimental::optional<int>) {} // warns, because:
    static_assert(not std::is_trivially_copyable_v<std::experimental::optional<int>>);
    

    The test is somewhat naive; the optimizer is capable of eliding the copy constructor of std::experimental::optional<int>. But there is no "weight" threshold. Indeed, the check does not warn on std::array<int, 1024>:

    void f(std::array<int, 1024>) {} // does not warn, because:
    static_assert(std::is_trivially_copyable_v<std::array<int, 1024>>);
    

    Demo.