Skip to content

Commit c60ccbc

Browse files
committed
Thread Safety Analysis: Convert CapabilityExpr::CapExpr to hold flags
Rather than holding a single bool, switch it to contain flags, which is both more descriptive and simplifies adding more flags in subsequent changes. NFC.
1 parent 45a3056 commit c60ccbc

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -271,26 +271,30 @@ class CFGWalker {
271271
// translateAttrExpr needs it, but that should be moved too.
272272
class CapabilityExpr {
273273
private:
274-
/// The capability expression and whether it's negated.
275-
llvm::PointerIntPair<const til::SExpr *, 1, bool> CapExpr;
274+
/// The capability expression and flags.
275+
llvm::PointerIntPair<const til::SExpr *, 1, unsigned> CapExpr;
276276

277277
/// The kind of capability as specified by @ref CapabilityAttr::getName.
278278
StringRef CapKind;
279279

280280
public:
281-
CapabilityExpr() : CapExpr(nullptr, false) {}
282-
CapabilityExpr(const til::SExpr *E, StringRef Kind, bool Neg)
283-
: CapExpr(E, Neg), CapKind(Kind) {}
281+
static constexpr unsigned FlagNegative = 1u << 0;
282+
283+
CapabilityExpr() : CapExpr(nullptr, 0) {}
284+
CapabilityExpr(const til::SExpr *E, StringRef Kind, unsigned Flags)
285+
: CapExpr(E, Flags), CapKind(Kind) {}
284286

285287
// Don't allow implicitly-constructed StringRefs since we'll capture them.
286-
template <typename T> CapabilityExpr(const til::SExpr *, T, bool) = delete;
288+
template <typename T>
289+
CapabilityExpr(const til::SExpr *, T, unsigned) = delete;
287290

288291
const til::SExpr *sexpr() const { return CapExpr.getPointer(); }
289292
StringRef getKind() const { return CapKind; }
290-
bool negative() const { return CapExpr.getInt(); }
293+
bool negative() const { return CapExpr.getInt() & FlagNegative; }
291294

292295
CapabilityExpr operator!() const {
293-
return CapabilityExpr(CapExpr.getPointer(), CapKind, !CapExpr.getInt());
296+
return CapabilityExpr(CapExpr.getPointer(), CapKind,
297+
CapExpr.getInt() ^ FlagNegative);
294298
}
295299

296300
bool equals(const CapabilityExpr &other) const {

clang/lib/Analysis/ThreadSafety.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,7 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
18391839
if (isa<CXXConstructExpr>(Exp))
18401840
Self = Placeholder.first;
18411841
if (TagT->getDecl()->hasAttr<ScopedLockableAttr>())
1842-
Scp = CapabilityExpr(Placeholder.first, Placeholder.second, false);
1842+
Scp = CapabilityExpr(Placeholder.first, Placeholder.second, 0);
18431843
}
18441844

18451845
assert(Loc.isInvalid());
@@ -1982,7 +1982,7 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
19821982
Cp.isInvalid() && CBTE) {
19831983
if (auto Object = Analyzer->ConstructedObjects.find(CBTE->getSubExpr());
19841984
Object != Analyzer->ConstructedObjects.end())
1985-
Cp = CapabilityExpr(Object->second, StringRef("mutex"), false);
1985+
Cp = CapabilityExpr(Object->second, StringRef("mutex"), 0);
19861986
}
19871987
const FactEntry *Fact = FSet.findLock(Analyzer->FactMan, Cp);
19881988
if (!Fact) {

clang/lib/Analysis/ThreadSafetyCommon.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
173173
Self,
174174
ClassifyDiagnostic(
175175
cast<CXXMethodDecl>(D)->getFunctionObjectParameterType()),
176-
false);
176+
0);
177177
else // For most attributes.
178178
return translateAttrExpr(AttrExp, &Ctx);
179179
}
@@ -197,22 +197,22 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
197197
// The "*" expr is a universal lock, which essentially turns off
198198
// checks until it is removed from the lockset.
199199
return CapabilityExpr(new (Arena) til::Wildcard(), StringRef("wildcard"),
200-
false);
200+
0);
201201
else
202202
// Ignore other string literals for now.
203203
return CapabilityExpr();
204204
}
205205

206-
bool Neg = false;
206+
unsigned ExprFlags = 0;
207207
if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
208208
if (OE->getOperator() == OO_Exclaim) {
209-
Neg = true;
209+
ExprFlags |= CapabilityExpr::FlagNegative;
210210
AttrExp = OE->getArg(0);
211211
}
212212
}
213213
else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
214214
if (UO->getOpcode() == UO_LNot) {
215-
Neg = true;
215+
ExprFlags |= CapabilityExpr::FlagNegative;
216216
AttrExp = UO->getSubExpr()->IgnoreImplicit();
217217
}
218218
}
@@ -229,9 +229,9 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
229229
// Hack to deal with smart pointers -- strip off top-level pointer casts.
230230
if (const auto *CE = dyn_cast<til::Cast>(E)) {
231231
if (CE->castOpcode() == til::CAST_objToPtr)
232-
return CapabilityExpr(CE->expr(), Kind, Neg);
232+
return CapabilityExpr(CE->expr(), Kind, ExprFlags);
233233
}
234-
return CapabilityExpr(E, Kind, Neg);
234+
return CapabilityExpr(E, Kind, ExprFlags);
235235
}
236236

237237
til::LiteralPtr *SExprBuilder::createVariable(const VarDecl *VD) {

0 commit comments

Comments
 (0)