diff options
author | DeLesley Hutchins <delesley@google.com> | 2014-08-04 16:10:59 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2014-08-04 16:10:59 +0000 |
commit | 4266522ab9a5c1c868e42b0d617a1136408cdec7 (patch) | |
tree | 6a27935cfd12d6f8370d823d190ec1e172bce1fc /clang/lib/Analysis/ThreadSafetyCommon.cpp | |
parent | 0b2ebcb49dd0d5dc61a122025c207a6ff54f1ad1 (diff) | |
download | llvm-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.cpp | 47 |
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()); } } |