diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -2087,6 +2087,19 @@ SourceRange(Loc, Loc)); } +static Expr *UnpackConstruction(Expr *E) { + if (auto *CE = dyn_cast(E)) + if (CE->getCastKind() == CK_NoOp) + E = CE->getSubExpr()->IgnoreParens(); + if (auto *CE = dyn_cast(E)) + if (CE->getCastKind() == CK_ConstructorConversion || + CE->getCastKind() == CK_UserDefinedConversion) + E = CE->getSubExpr(); + if (auto *BTE = dyn_cast(E)) + E = BTE->getSubExpr(); + return E; +} + void BuildLockset::VisitDeclStmt(const DeclStmt *S) { // adjust the context LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx); @@ -2101,13 +2114,7 @@ // handle constructors that involve temporaries if (auto *EWC = dyn_cast(E)) E = EWC->getSubExpr()->IgnoreParens(); - if (auto *CE = dyn_cast(E)) - if (CE->getCastKind() == CK_NoOp || - CE->getCastKind() == CK_ConstructorConversion || - CE->getCastKind() == CK_UserDefinedConversion) - E = CE->getSubExpr()->IgnoreParens(); - if (auto *BTE = dyn_cast(E)) - E = BTE->getSubExpr()->IgnoreParens(); + E = UnpackConstruction(E); if (const auto *CE = dyn_cast(E)) { const auto *CtorD = dyn_cast_or_null(CE->getConstructor()); diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1683,6 +1683,13 @@ a = 5; } +#ifdef __cpp_guaranteed_copy_elision + void const_lock() { + const MutexLock mulock = MutexLock(&mu1); + a = 5; + } +#endif + void foo2() { ReaderMutexLock mulock1(&mu1); if (getBool()) {