Skip to content

False positive on [[lifetimebound]] when returning a prvalue #113472

@brevzin

Description

@brevzin

Consider this example:

template <class T>
struct Optional {
    bool flag;
    union { T val; };

    auto value() && [[clang::lifetimebound]] -> T&&;

    template <class U>
    auto value_or(U&& rhs) && [[clang::lifetimebound]] -> decltype(auto) {
        return flag ? (T&&)val : (U&&)rhs;
    }
};

auto f() -> Optional<int const>;

auto g() -> int {
    auto&& r1 = f().value();
    auto&& r2 = f().value_or(-1);
    auto&& r3 = f().value_or(42.0);
    return r1 + r2 + r3;
}

This is a very reduced implementation of Optional. In the usage in g, r1 and r2 are dangling references but r3 is not (it's a reference bound to a temporary of type double so it's lifetime extended). gcc's -Wdangling-reference warning correctly diagnoses r1 and r2 as problematic and correctly does not diagnose r3.

clang doesn't have -Wdangling-reference, but I can add [[clang::lifetimebound]] to get the same behavior. The problem is that it over-diagnoses:

<source>:17:17: warning: temporary bound to local reference 'r1' will be destroyed at the end of the full-expression [-Wdangling]
   17 |     auto&& r1 = f().value();
      |                 ^~~
<source>:18:17: warning: temporary bound to local reference 'r2' will be destroyed at the end of the full-expression [-Wdangling]
   18 |     auto&& r2 = f().value_or(-1);
      |                 ^~~
<source>:19:17: warning: temporary bound to local reference 'r3' will be destroyed at the end of the full-expression [-Wdangling]
   19 |     auto&& r3 = f().value_or(42.0);
      |                 ^~~

r3 isn't a problem though, because that specialization of value_or() returns double.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:diagnosticsNew/improved warning or error message in Clang, but not in clang-tidy or static analyzer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions