clang: lib/StaticAnalyzer/Core/SymbolManager.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25#include "llvm/ADT/FoldingSet.h"

26#include "llvm/ADT/STLExtras.h"

27#include "llvm/Support/Casting.h"

28#include "llvm/Support/Compiler.h"

29#include "llvm/Support/ErrorHandling.h"

30#include "llvm/Support/raw_ostream.h"

31#include

32

33using namespace clang;

34using namespace ento;

35

36void SymExpr::anchor() {}

37

43

45

47 OS << '(';

49 OS << ')';

50}

51

53 const llvm::APSInt &Value) {

54 if (Value.isUnsigned())

55 OS << Value.getZExtValue();

56 else

57 OS << Value.getSExtValue();

58 if (Value.isUnsigned())

59 OS << 'U';

60}

61

65}

66

68 os << '(' << ToTy << ") (";

70 os << ')';

71}

72

75 bool Binary = isa(Operand);

76 if (Binary)

77 os << '(';

79 if (Binary)

80 os << ')';

81}

82

85 if (S)

87 else

88 os << ", no stmt";

89 os << ", #" << Count << '}';

90}

91

95}

96

99}

100

103}

104

105void SymbolData::anchor() {}

106

109}

110

112 return itr == X.itr;

113}

114

116 return itr != X.itr;

117}

118

120 itr.push_back(SE);

121}

122

124 assert(!itr.empty() && "attempting to iterate on an 'end' iterator");

125 expand();

126 return *this;

127}

128

130 assert(!itr.empty() && "attempting to dereference an 'end' iterator");

131 return itr.back();

132}

133

134void SymExpr::symbol_iterator::expand() {

135 const SymExpr *SE = itr.pop_back_val();

136

138 case SymExpr::SymbolRegionValueKind:

139 case SymExpr::SymbolConjuredKind:

140 case SymExpr::SymbolDerivedKind:

141 case SymExpr::SymbolExtentKind:

142 case SymExpr::SymbolMetadataKind:

143 return;

144 case SymExpr::SymbolCastKind:

145 itr.push_back(cast(SE)->getOperand());

146 return;

147 case SymExpr::UnarySymExprKind:

148 itr.push_back(cast(SE)->getOperand());

149 return;

150 case SymExpr::SymIntExprKind:

151 itr.push_back(cast(SE)->getLHS());

152 return;

153 case SymExpr::IntSymExprKind:

154 itr.push_back(cast(SE)->getRHS());

155 return;

156 case SymExpr::SymSymExprKind: {

157 const auto *x = cast(SE);

158 itr.push_back(x->getLHS());

159 itr.push_back(x->getRHS());

160 return;

161 }

162 }

163 llvm_unreachable("unhandled expansion case");

164}

165

167 return T;

168}

169

171 return R->getValueType();

172}

173

175 ASTContext &Ctx = R->getMemRegionManager().getContext();

177}

178

180 return T;

181}

182

184 return R->getValueType();

185}

186

188 T = T.getCanonicalType();

189

191 return true;

192

194 return true;

195

197 return true;

198

199 return false;

200}

201

204 auto &dependencies = SymbolDependencies[Primary];

205 if (!dependencies) {

206 dependencies = std::make_unique();

207 }

208 dependencies->push_back(Dependent);

209}

210

213 SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);

214 if (I == SymbolDependencies.end())

215 return nullptr;

216 return I->second.get();

217}

218

219void SymbolReaper::markDependentsLive(SymbolRef sym) {

220

221 SymbolMapTy::iterator LI = TheLiving.find(sym);

222 assert(LI != TheLiving.end() && "The primary symbol is not live.");

223 if (LI->second == HaveMarkedDependents)

224 return;

225 LI->second = HaveMarkedDependents;

226

228 for (const auto I : *Deps) {

229 if (TheLiving.contains(I))

230 continue;

231 markLive(I);

232 }

233 }

234}

235

237 TheLiving[sym] = NotProcessed;

238 markDependentsLive(sym);

239}

240

243 markElementIndicesLive(region);

244}

245

247 LazilyCopiedRegionRoots.insert(region->getBaseRegion());

248}

249

251 for (auto SR = dyn_cast(region); SR;

252 SR = dyn_cast(SR->getSuperRegion())) {

253 if (const auto ER = dyn_cast(SR)) {

254 SVal Idx = ER->getIndex();

256 markLive(Sym);

257 }

258 }

259}

260

262 if (isa(sym))

263 MetadataInUse.insert(sym);

264}

265

267

268

269

270

272 if (LiveRegionRoots.count(MR))

273 return true;

274

275 if (const auto *SR = dyn_cast(MR))

276 return isLive(SR->getSymbol());

277

278 if (const auto *VR = dyn_cast(MR))

279 return isLive(VR, true);

280

281

282

283

284

285 return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);

286}

287

288bool SymbolReaper::isLazilyCopiedRegion(const MemRegion *MR) const {

289

290 return LazilyCopiedRegionRoots.count(MR->getBaseRegion());

291}

292

293bool SymbolReaper::isReadableRegion(const MemRegion *MR) {

294 return isLiveRegion(MR) || isLazilyCopiedRegion(MR);

295}

296

298 if (TheLiving.count(sym)) {

299 markDependentsLive(sym);

300 return true;

301 }

302

303 bool KnownLive;

304

305 switch (sym->getKind()) {

306 case SymExpr::SymbolRegionValueKind:

307 KnownLive = isReadableRegion(cast(sym)->getRegion());

308 break;

309 case SymExpr::SymbolConjuredKind:

310 KnownLive = false;

311 break;

312 case SymExpr::SymbolDerivedKind:

313 KnownLive = isLive(cast(sym)->getParentSymbol());

314 break;

315 case SymExpr::SymbolExtentKind:

316 KnownLive = isLiveRegion(cast(sym)->getRegion());

317 break;

318 case SymExpr::SymbolMetadataKind:

319 KnownLive = MetadataInUse.count(sym) &&

320 isLiveRegion(cast(sym)->getRegion());

321 if (KnownLive)

322 MetadataInUse.erase(sym);

323 break;

324 case SymExpr::SymIntExprKind:

325 KnownLive = isLive(cast(sym)->getLHS());

326 break;

327 case SymExpr::IntSymExprKind:

328 KnownLive = isLive(cast(sym)->getRHS());

329 break;

330 case SymExpr::SymSymExprKind:

331 KnownLive = isLive(cast(sym)->getLHS()) &&

332 isLive(cast(sym)->getRHS());

333 break;

334 case SymExpr::SymbolCastKind:

335 KnownLive = isLive(cast(sym)->getOperand());

336 break;

337 case SymExpr::UnarySymExprKind:

338 KnownLive = isLive(cast(sym)->getOperand());

339 break;

340 }

341

342 if (KnownLive)

343 markLive(sym);

344

345 return KnownLive;

346}

347

348bool

350 if (LCtx == nullptr)

351 return false;

352

353 if (LCtx != ELCtx) {

354

355

356 if (LCtx->isParentOf(ELCtx))

357 return false;

358 return true;

359 }

360

361

362

363 if (Loc)

364 return true;

365

367}

368

371

372 if (!VarContext)

373 return true;

374

375 if (!LCtx)

376 return false;

378

379 if (VarContext == CurrentContext) {

380

381 if (Loc)

382 return true;

383

384

385

386 if (isa(Loc))

387 return true;

388

390 return true;

391

392 if (!includeStoreBindings)

393 return false;

394

395 unsigned &cachedQuery =

396 const_cast<SymbolReaper *>(this)->includedRegionCache[VR];

397

398 if (cachedQuery) {

399 return cachedQuery == 1;

400 }

401

402

403 if (Store store = reapedStore.getStore()) {

404 bool hasRegion =

405 reapedStore.getStoreManager().includedInBindings(store, VR);

406 cachedQuery = hasRegion ? 1 : 2;

407 return hasRegion;

408 }

409

410 return false;

411 }

412

413 return VarContext->isParentOf(CurrentContext);

414}

Defines the clang::ASTContext interface.

This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...

static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the Objective-C statement AST node classes.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

CanQualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

StringRef getOpcodeStr() const

ASTContext & getASTContext() const LLVM_READONLY

This represents one expression.

bool isLive(const CFGBlock *B, const VarDecl *D)

Return true if a variable is live at the end of a specified block.

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

bool isParentOf(const LocationContext *LC) const

const Decl * getDecl() const

const StackFrameContext * getStackFrame() const

A (possibly-)qualified type.

It represents a stack frame of the call stack (based on CallEvent).

int64_t getID(const ASTContext &Context) const

bool isIntegralOrEnumerationType() const

Determine whether this type is an integral or enumeration type.

bool isRecordType() const

static StringRef getOpcodeStr(Opcode Op)

getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to,...

static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value)

static bool isLocType(QualType T)

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

llvm::iterator_range< SymExpr::symbol_iterator > symbols() const

Iterator over symbols that the current symbol depends on.

symbol_iterator()=default

bool operator!=(const symbol_iterator &X) const

symbol_iterator & operator++()

bool operator==(const symbol_iterator &X) const

const SymExpr * operator*()

virtual void dumpToStream(raw_ostream &os) const

virtual void dump() const

SymbolID getSymbolID() const

Get a unique identifier for this symbol.

void dumpToStream(raw_ostream &os) const override

StringRef getKindStr() const override

Get a string representation of the kind of the region.

void dumpToStream(raw_ostream &os) const override

QualType getType() const override

LLVM_ATTRIBUTE_RETURNS_NONNULL SymbolRef getParentSymbol() const

StringRef getKindStr() const override

Get a string representation of the kind of the region.

void dumpToStream(raw_ostream &os) const override

QualType getType() const override

LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const SubRegion * getRegion() const

void dumpToStream(raw_ostream &os) const override

QualType getType() const override

StringRef getKindStr() const override

Get a string representation of the kind of the region.

void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)

Add artificial symbol dependency.

const SymbolRefSmallVectorTy * getDependentSymbols(const SymbolRef Primary)

static bool canSymbolicate(QualType T)

A class responsible for cleaning up unused symbols.

void markLive(SymbolRef sym)

Unconditionally marks a symbol as live.

void markElementIndicesLive(const MemRegion *region)

void markInUse(SymbolRef sym)

Marks a symbol as important to a checker.

bool isLiveRegion(const MemRegion *region)

void markLazilyCopied(const MemRegion *region)

bool isLive(SymbolRef sym)

void dumpToStream(raw_ostream &os) const override

QualType getType() const override

StringRef getKindStr() const override

Get a string representation of the kind of the region.

void dumpToStream(raw_ostream &os) const override

const VarDecl * getDecl() const override=0

const StackFrameContext * getStackFrame() const

It might return null.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

const void * Store

Store - This opaque type encapsulates an immutable mapping from locations to values.

The JSON file list parser is used to communicate input to InstallAPI.

const FunctionProtoType * T