Index: include/clang/Analysis/Analyses/ThreadSafetyTIL.h =================================================================== --- include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -909,15 +909,10 @@ public: static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } - Project(SExpr *R, StringRef SName) - : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) - { } Project(SExpr *R, const clang::ValueDecl *Cvd) - : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) - { } - Project(const Project &P, SExpr *R) - : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) - { } + : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) { + assert(Cvd && "ValueDecl must not be null"); + } SExpr *record() { return Rec; } const SExpr *record() const { return Rec; } @@ -931,10 +926,14 @@ } StringRef slotName() const { - if (Cvdecl) + if (Cvdecl->getDeclName().isIdentifier()) return Cvdecl->getName(); - else - return SlotName; + if (!SlotName) { + SlotName = ""; + llvm::raw_string_ostream OS(*SlotName); + Cvdecl->printName(OS); + } + return *SlotName; } template @@ -953,7 +952,7 @@ private: SExpr* Rec; - StringRef SlotName; + mutable llvm::Optional SlotName; const clang::ValueDecl *Cvdecl; }; Index: test/SemaCXX/warn-thread-safety-analysis.cpp =================================================================== --- test/SemaCXX/warn-thread-safety-analysis.cpp +++ test/SemaCXX/warn-thread-safety-analysis.cpp @@ -5233,3 +5233,18 @@ } // expected-warning {{mutex 'lock_' is still held at the end of function}} Mutex lock_ ACQUIRED_BEFORE(""); }; + +namespace PR34800 { +struct A { + operator int() const; +}; +struct B { + bool g() __attribute__((locks_excluded(h))); // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} + int h; +}; +struct C { + B *operator[](int); +}; +C c; +void f() { c[A()]->g(); } +} // namespace PR34800