Skip to content

[Clang] Static analyzer (with assertions) crashes when dealing with std::call_once #139647

Open
@ziqingluo-90

Description

@ziqingluo-90

A minimal example (https://godbolt.org/z/o99n7db3e):

#include <mutex>

class T {
    public: 
    T () {}
};

bool check() {
  static std::once_flag flag;
  auto fun = [](T S)->void{};
  std::call_once(flag, fun, T());

}

I think the issue is in fact in BodyFarm instead of CSA, so please help me to CC more appropriate community members and add proper tags if possible.

CSA uses BodyFarm to create the definition of std::call_once.

/// Create a fake body for std::call_once.
/// Emulates the following function body:
///
/// \code
/// typedef struct once_flag_s {
///   unsigned long __state = 0;
/// } once_flag;
/// template<class Callable>
/// void call_once(once_flag& o, Callable func) {
///   if (!o.__state) {
///     func();
///   }
///   o.__state = 1;
/// }
/// \endcode

When BodyFarm crafts the definition, it needs to create an lvalue-to-rvalue conversion on the parameter of type C++ class T.

   Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
    if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
      QualType PTy = PDecl->getType().getNonReferenceType();
      ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
    }

However, in ImplicitCastExpr::Create:

  // Per C++ [conv.lval]p3, lvalue-to-rvalue conversions on class and
  // std::nullptr_t have special semantics not captured by CK_LValueToRValue.
  assert((Kind != CK_LValueToRValue ||
          !(T->isNullPtrType() || T->getAsCXXRecordDecl())) &&
         "invalid type for lvalue-to-rvalue conversion");

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions