aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafetyCommon.cpp
diff options
context:
space:
mode:
authorAaron Puchert <aaron.puchert@sap.com>2022-04-29 22:12:21 +0200
committerAaron Puchert <aaron.puchert@sap.com>2022-04-29 22:30:33 +0200
commitf8afb8fdedae04ad2670857c97925c439d47d862 (patch)
tree977fc59a82e8bb784221de9ca3fc86887083749f /clang/lib/Analysis/ThreadSafetyCommon.cpp
parentd65c922450d1fdf0f44f4a10a8f33b11c6c01bf5 (diff)
downloadllvm-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.cpp37
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.