aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafetyCommon.cpp
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2014-08-04 16:10:59 +0000
committerDeLesley Hutchins <delesley@google.com>2014-08-04 16:10:59 +0000
commit4266522ab9a5c1c868e42b0d617a1136408cdec7 (patch)
tree6a27935cfd12d6f8370d823d190ec1e172bce1fc /clang/lib/Analysis/ThreadSafetyCommon.cpp
parent0b2ebcb49dd0d5dc61a122025c207a6ff54f1ad1 (diff)
downloadllvm-4266522ab9a5c1c868e42b0d617a1136408cdec7.zip
llvm-4266522ab9a5c1c868e42b0d617a1136408cdec7.tar.gz
llvm-4266522ab9a5c1c868e42b0d617a1136408cdec7.tar.bz2
Thread safety analysis: Add support for negative requirements, which are
capability expressions of the form !expr, and denote a capability that must not be held. llvm-svn: 214725
Diffstat (limited to 'clang/lib/Analysis/ThreadSafetyCommon.cpp')
-rw-r--r--clang/lib/Analysis/ThreadSafetyCommon.cpp47
1 files changed, 35 insertions, 12 deletions
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 56feba7..e9b1f64 100644
--- a/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -105,10 +105,10 @@ inline bool isCalleeArrow(const Expr *E) {
/// \param D The declaration to which the attribute is attached.
/// \param DeclExp An expression involving the Decl to which the attribute
/// is attached. E.g. the call to a function.
-til::SExpr *SExprBuilder::translateAttrExpr(const Expr *AttrExp,
- const NamedDecl *D,
- const Expr *DeclExp,
- VarDecl *SelfDecl) {
+CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
+ const NamedDecl *D,
+ const Expr *DeclExp,
+ VarDecl *SelfDecl) {
// If we are processing a raw attribute expression, with no substitutions.
if (!DeclExp)
return translateAttrExpr(AttrExp, nullptr);
@@ -163,26 +163,48 @@ til::SExpr *SExprBuilder::translateAttrExpr(const Expr *AttrExp,
/// \brief Translate a clang expression in an attribute to a til::SExpr.
// This assumes a CallingContext has already been created.
-til::SExpr *SExprBuilder::translateAttrExpr(const Expr *AttrExp,
- CallingContext *Ctx) {
- if (const StringLiteral* SLit = dyn_cast_or_null<StringLiteral>(AttrExp)) {
+CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
+ CallingContext *Ctx) {
+ if (!AttrExp)
+ return CapabilityExpr(nullptr, false);
+
+ if (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 new (Arena) til::Wildcard();
+ return CapabilityExpr(new (Arena) til::Wildcard(), false);
else
// Ignore other string literals for now.
- return nullptr;
+ return CapabilityExpr(nullptr, false);
+ }
+
+ bool Neg = false;
+ if (auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
+ if (OE->getOperator() == OO_Exclaim) {
+ Neg = true;
+ AttrExp = OE->getArg(0);
+ }
+ }
+ else if (auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
+ if (UO->getOpcode() == UO_LNot) {
+ Neg = true;
+ AttrExp = UO->getSubExpr();
+ }
}
til::SExpr *E = translate(AttrExp, Ctx);
+ // Trap mutex expressions like nullptr, or 0.
+ // Any literal value is nonsense.
+ if (!E || isa<til::Literal>(E))
+ return CapabilityExpr(nullptr, false);
+
// Hack to deal with smart pointers -- strip off top-level pointer casts.
if (auto *CE = dyn_cast_or_null<til::Cast>(E)) {
if (CE->castOpcode() == til::CAST_objToPtr)
- return CE->expr();
+ return CapabilityExpr(CE->expr(), Neg);
}
- return E;
+ return CapabilityExpr(E, Neg);
}
@@ -357,7 +379,8 @@ til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
LRCallCtx.SelfArg = SelfE;
LRCallCtx.NumArgs = CE->getNumArgs();
LRCallCtx.FunArgs = CE->getArgs();
- return translateAttrExpr(At->getArg(), &LRCallCtx);
+ return const_cast<til::SExpr*>(
+ translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
}
}