431 changes: 431 additions & 0 deletions lib/StaticAnalyzer/Checkers/PthreadLockCheckerV2.cpp

Large diffs are not rendered by default.

54 changes: 50 additions & 4 deletions lib/StaticAnalyzer/Core/MemRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,18 @@ void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
}

void GhostVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
const SmartStateTrait &Trait,
const MemRegion *SReg) {
ID.AddInteger(GhostVarRegionKind);
ID.AddInteger(Trait.getTraitID());
ID.AddPointer(SReg);
}

void GhostVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ProfileRegion(ID, Trait, getSuperRegion());
}

void GhostFieldRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
const SmartStateTrait &Trait,
const MemRegion *SReg) {
Expand Down Expand Up @@ -551,6 +563,10 @@ void VarRegion::dumpToStream(raw_ostream &os) const {
os << *cast<VarDecl>(D);
}

void GhostVarRegion::dumpToStream(raw_ostream &os) const {
os << getTrait().getTraitDescription();
}

void GhostFieldRegion::dumpToStream(raw_ostream &os) const {
os << getTrait().getTraitDescription() << '{' << getSuperRegion() << '}';
}
Expand Down Expand Up @@ -770,6 +786,26 @@ MemRegionManager::getGhostSpaceRegion(const SmartStateTrait &Trait) {
return R;
}

const MemSpaceRegion *
MemRegionManager::getPreferredSpaceRegion(const SmartStateTrait &Trait) {
if (Trait.hasDefaultMemSpace())
return getGhostSpaceRegion(Trait);
switch (MemRegion::Kind K = Trait.getTraitMemSpacePreference()) {
case MemRegion::GlobalImmutableSpaceRegionKind:
case MemRegion::GlobalInternalSpaceRegionKind:
case MemRegion::GlobalSystemSpaceRegionKind:
return getGlobalsRegion(K);
case MemRegion::HeapSpaceRegionKind:
return getHeapRegion();
case MemRegion::CodeSpaceRegionKind:
return getCodeRegion();
case MemRegion::UnknownSpaceRegionKind:
return getUnknownRegion();
default:
llvm_unreachable("Unsupported preferred memory space!");
}
}

//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -936,16 +972,25 @@ MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
}

const GhostVarRegion *
MemRegionManager::getGhostVarRegion(const SmartStateTrait &Trait,
const MemRegion *superRegion) {
if (!superRegion)
superRegion = getPreferredSpaceRegion(Trait);
return getSubRegion<GhostVarRegion>(Trait, superRegion);
}

const GhostFieldRegion *
MemRegionManager::getGhostFieldRegion(const SmartStateTrait &Trait,
const MemRegion *superRegion) {
return getSubRegion<GhostFieldRegion>(Trait, superRegion);
}

const GhostSymbolicRegion *
MemRegionManager::getGhostSymbolicRegion(const SmartStateTrait &Trait,
SymbolRef Sym) {
return getSubRegion<GhostSymbolicRegion>(Sym, getGhostSpaceRegion(Trait));
const GhostSymbolicRegion *MemRegionManager::getGhostSymbolicRegion(
const SmartStateTrait &Trait, SymbolRef Sym, const MemRegion *superRegion) {
if (!superRegion)
superRegion = getPreferredSpaceRegion(Trait);
return getSubRegion<GhostSymbolicRegion>(Sym, superRegion);
}

const CompoundLiteralRegion*
Expand Down Expand Up @@ -1289,6 +1334,7 @@ RegionOffset MemRegion::getAsOffset() const {
case ObjCStringRegionKind:
case VarRegionKind:
case CXXTempObjectRegionKind:
case GhostVarRegionKind:
case GhostSymbolicRegionKind:
// Usual base regions.
goto Finish;
Expand Down
5 changes: 5 additions & 0 deletions lib/StaticAnalyzer/Core/RegionStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,11 @@ void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
return;
}

if (isa<GhostVarRegion>(baseR)) {
AddToWorkList(baseR, &C);
return;
}

if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
if (SymReaper.isLive(SR->getSymbol()))
AddToWorkList(SR, &C);
Expand Down
1 change: 1 addition & 0 deletions lib/StaticAnalyzer/Core/Store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
case MemRegion::VarRegionKind:
case MemRegion::CXXTempObjectRegionKind:
case MemRegion::CXXBaseObjectRegionKind:
case MemRegion::GhostVarRegionKind:
case MemRegion::GhostFieldRegionKind:
case MemRegion::GhostSymbolicRegionKind:
return MakeElementRegion(R, PointeeTy);
Expand Down
3 changes: 3 additions & 0 deletions lib/StaticAnalyzer/Core/SymbolManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
return isLive(VR, true);

if (isa<GhostVarRegion>(MR))
return true;

// FIXME: This is a gross over-approximation. What we really need is a way to
// tell if anything still refers to this region. Unlike SymbolicRegions,
// AllocaRegions don't have associated symbols, though, so we don't actually
Expand Down
1 change: 1 addition & 0 deletions test/Analysis/pthreadlock.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.PthreadLock -verify %s
// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.PthreadLockV2 -verify %s

// Tests performing normal locking patterns and wrong locking orders

Expand Down