diff options
author | Aaron Puchert <aaron.puchert@sap.com> | 2022-04-29 22:12:21 +0200 |
---|---|---|
committer | Aaron Puchert <aaron.puchert@sap.com> | 2022-04-29 22:30:33 +0200 |
commit | f8afb8fdedae04ad2670857c97925c439d47d862 (patch) | |
tree | 977fc59a82e8bb784221de9ca3fc86887083749f /clang/lib/Analysis/ThreadSafetyCommon.cpp | |
parent | d65c922450d1fdf0f44f4a10a8f33b11c6c01bf5 (diff) | |
download | llvm-f8afb8fdedae04ad2670857c97925c439d47d862.zip llvm-f8afb8fdedae04ad2670857c97925c439d47d862.tar.gz llvm-f8afb8fdedae04ad2670857c97925c439d47d862.tar.bz2 |
Thread safety analysis: Store capability kind in CapabilityExpr
This should make us print the right capability kind in many more cases,
especially when attributes name multiple capabilities of different kinds.
Previously we were trying to deduce the capability kind from the
original attribute, but most attributes can name multiple capabilities,
which could be of different kinds. So instead we derive the kind when
translating the attribute expression, and then store it in the returned
CapabilityExpr. Then we can extract the corresponding capability name
when we need it, which saves us lots of plumbing and almost guarantees
that the name is right.
I didn't bother adding any tests for this because it's just a usability
improvement and it's pretty much evident from the code that we don't
fall back to "mutex" anymore (save for a few cases that I'll address in
a separate change).
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D124131
Diffstat (limited to 'clang/lib/Analysis/ThreadSafetyCommon.cpp')
-rw-r--r-- | clang/lib/Analysis/ThreadSafetyCommon.cpp | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index e6b4a05..66413f8 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -86,6 +86,28 @@ static bool isCalleeArrow(const Expr *E) { return ME ? ME->isArrow() : false; } +static StringRef ClassifyDiagnostic(const CapabilityAttr *A) { + return A->getName(); +} + +static StringRef ClassifyDiagnostic(QualType VDT) { + // We need to look at the declaration of the type of the value to determine + // which it is. The type should either be a record or a typedef, or a pointer + // or reference thereof. + if (const auto *RT = VDT->getAs<RecordType>()) { + if (const auto *RD = RT->getDecl()) + if (const auto *CA = RD->getAttr<CapabilityAttr>()) + return ClassifyDiagnostic(CA); + } else if (const auto *TT = VDT->getAs<TypedefType>()) { + if (const auto *TD = TT->getDecl()) + if (const auto *CA = TD->getAttr<CapabilityAttr>()) + return ClassifyDiagnostic(CA); + } else if (VDT->isPointerType() || VDT->isReferenceType()) + return ClassifyDiagnostic(VDT->getPointeeType()); + + return "mutex"; +} + /// Translate a clang expression in an attribute to a til::SExpr. /// Constructs the context from D, DeclExp, and SelfDecl. /// @@ -152,16 +174,17 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx) { if (!AttrExp) - return CapabilityExpr(nullptr, false); + return CapabilityExpr(); if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) { if (SLit->getString() == StringRef("*")) // The "*" expr is a universal lock, which essentially turns off // checks until it is removed from the lockset. - return CapabilityExpr(new (Arena) til::Wildcard(), false); + return CapabilityExpr(new (Arena) til::Wildcard(), StringRef("wildcard"), + false); else // Ignore other string literals for now. - return CapabilityExpr(nullptr, false); + return CapabilityExpr(); } bool Neg = false; @@ -183,14 +206,16 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, // Trap mutex expressions like nullptr, or 0. // Any literal value is nonsense. if (!E || isa<til::Literal>(E)) - return CapabilityExpr(nullptr, false); + return CapabilityExpr(); + + StringRef Kind = ClassifyDiagnostic(AttrExp->getType()); // Hack to deal with smart pointers -- strip off top-level pointer casts. if (const auto *CE = dyn_cast<til::Cast>(E)) { if (CE->castOpcode() == til::CAST_objToPtr) - return CapabilityExpr(CE->expr(), Neg); + return CapabilityExpr(CE->expr(), Kind, Neg); } - return CapabilityExpr(E, Neg); + return CapabilityExpr(E, Kind, Neg); } // Translate a clang statement or expression to a TIL expression. |