From: Alexander Kornienko Date: Wed, 4 Oct 2017 10:24:36 +0000 (+0000) Subject: Fix assertion failure in thread safety analysis (PR34800). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74f99c5856494770f620e7848c38fd6b63d00e26;p=clang Fix assertion failure in thread safety analysis (PR34800). Summary: Fix an assertion failure (http://llvm.org/PR34800) and clean up unused code relevant to the fixed logic. A bit of context: when `SExprBuilder::translateMemberExpr` is called on a member expression that involves a conversion operator, for example, `til::Project` constructor can't just call `getName()` on it, since the name is not a simple identifier. In order to handle this case I've introduced an optional string to print the member name to. I discovered that the other two `til::Project` constructors are not used, so it was better to delete them instead of ensuring they work correctly with the new logic. Reviewers: aaron.ballman Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D38458 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314895 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index be8a7105d7..17351622fb 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -909,15 +909,10 @@ class Project : public SExpr { 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 @@ public: } 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 @@ public: private: SExpr* Rec; - StringRef SlotName; + mutable llvm::Optional SlotName; const clang::ValueDecl *Cvdecl; }; diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 86a2915ae1..e6e9a0ac18 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -5233,3 +5233,18 @@ class acquired_before_empty_str { } // 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