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

1

2

3

4

5

6

7

8

9

10

11

12

28#include "llvm/ADT/ImmutableMap.h"

29#include "llvm/ADT/SmallPtrSet.h"

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

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

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

33#include

34

35using namespace clang;

36using namespace ento;

37

40

42 case Stmt::OpaqueValueExprClass:

43 if (const Expr *SE = cast(E)->getSourceExpr()) {

44 E = SE;

45 break;

46 }

47 return E;

48 case Stmt::ExprWithCleanupsClass:

49 E = cast(E)->getSubExpr();

50 break;

51 case Stmt::ConstantExprClass:

52 E = cast(E)->getSubExpr();

53 break;

54 case Stmt::CXXBindTemporaryExprClass:

55 E = cast(E)->getSubExpr();

56 break;

57 case Stmt::SubstNonTypeTemplateParmExprClass:

58 E = cast(E)->getReplacement();

59 break;

60 default:

61

62 return E;

63 }

64

66}

67

69 if (const auto *E = dyn_cast(S))

71 return S;

72}

73

77 L ? L->getStackFrame()

78 : nullptr) {}

79

81 const SVal* X = ExprBindings.lookup(E);

82 if (X) {

84 return V;

85 }

87}

88

92 assert(!isa(S) &&

93 "Use ExprEngine::hasMoreIteration()!");

94 assert((isa<Expr, ReturnStmt>(S)) &&

95 "Environment can only argue about Exprs, since only they express "

96 "a value! Any non-expression statement stored in Environment is a "

97 "result of a hack!");

99

100 switch (S->getStmtClass()) {

101 case Stmt::CXXBindTemporaryExprClass:

102 case Stmt::ExprWithCleanupsClass:

103 case Stmt::GenericSelectionExprClass:

104 case Stmt::ConstantExprClass:

105 case Stmt::ParenExprClass:

106 case Stmt::SubstNonTypeTemplateParmExprClass:

107 llvm_unreachable("Should have been handled by ignoreTransparentExprs");

108

109 case Stmt::AddrLabelExprClass:

110 case Stmt::CharacterLiteralClass:

111 case Stmt::CXXBoolLiteralExprClass:

112 case Stmt::CXXScalarValueInitExprClass:

113 case Stmt::ImplicitValueInitExprClass:

114 case Stmt::IntegerLiteralClass:

115 case Stmt::ObjCBoolLiteralExprClass:

116 case Stmt::CXXNullPtrLiteralExprClass:

117 case Stmt::ObjCStringLiteralClass:

118 case Stmt::StringLiteralClass:

119 case Stmt::TypeTraitExprClass:

120 case Stmt::SizeOfPackExprClass:

121 case Stmt::PredefinedExprClass:

122

124

125 case Stmt::ReturnStmtClass: {

126 const auto *RS = cast(S);

127 if (const Expr *RE = RS->getRetValue())

130 }

131

132

133 default:

135 }

136}

137

141 bool Invalidate) {

142 if (V.isUnknown()) {

143 if (Invalidate)

145 else

146 return Env;

147 }

149}

150

151namespace {

152

153class MarkLiveCallback final : public SymbolVisitor {

155

156public:

157 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}

158

159 bool VisitSymbol(SymbolRef sym) override {

160 SymReaper.markLive(sym);

161 return true;

162 }

163

164 bool VisitMemRegion(const MemRegion *R) override {

165 SymReaper.markLive(R);

166 return true;

167 }

168};

169

170}

171

172

173

174

175

176

177

178

183

184

185

187

188 MarkLiveCallback CB(SymReaper);

190

191 llvm::ImmutableMapRef<EnvironmentEntry, SVal>

192 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),

193 F.getTreeFactory());

194

195

198 SVal X = I.getData();

199

200 const Expr *E = dyn_cast(BlkExpr.getStmt());

201 if (E)

202 continue;

203

205

206 EBMapRef = EBMapRef.add(BlkExpr, X);

207

208

209 RSScaner.scan(X);

210 }

211 }

212

213 NewEnv.ExprBindings = EBMapRef.asImmutableMap();

214 return NewEnv;

215}

216

219 unsigned int Space, bool IsDot) const {

220 Indent(Out, Space, IsDot) << "\"environment\": ";

221

222 if (ExprBindings.isEmpty()) {

223 Out << "null," << NL;

224 return;

225 }

226

227 ++Space;

228 if (!LCtx) {

229

231 for (const auto &I : *this) {

232 const LocationContext *LC = I.first.getLocationContext();

233 if (FoundContexts.count(LC) == 0) {

234

235 LCtx = LC;

237 FoundContexts.insert(LCI);

238 }

239 }

240 }

241

242 assert(LCtx);

243

244 Out << "{ \"pointer\": \"" << (const void *)LCtx->getStackFrame()

245 << "\", \"items\": [" << NL;

247

249

250 bool HasItem = false;

251 unsigned int InnerSpace = Space + 1;

252

253

254 BindingsTy::iterator LastI = ExprBindings.end();

255 for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();

256 ++I) {

257 if (I->first.getLocationContext() != LC)

258 continue;

259

260 if (!HasItem) {

261 HasItem = true;

262 Out << '[' << NL;

263 }

264

265 const Stmt *S = I->first.getStmt();

266 (void)S;

267 assert(S != nullptr && "Expected non-null Stmt");

268

269 LastI = I;

270 }

271

272 for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();

273 ++I) {

274 if (I->first.getLocationContext() != LC)

275 continue;

276

277 const Stmt *S = I->first.getStmt();

278 Indent(Out, InnerSpace, IsDot)

279 << "{ \"stmt_id\": " << S->getID(Ctx) << ", \"kind\": \""

280 << S->getStmtClassName() << "\", \"pretty\": ";

281 S->printJson(Out, nullptr, PP, true);

282

283 Out << ", \"value\": ";

284 I->second.printJson(Out, true);

285

286 Out << " }";

287

288 if (I != LastI)

289 Out << ',';

290 Out << NL;

291 }

292

293 if (HasItem)

294 Indent(Out, --InnerSpace, IsDot) << ']';

295 else

296 Out << "null ";

297 });

298

299 Indent(Out, --Space, IsDot) << "]}," << NL;

300}

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

static const Expr * ignoreTransparentExprs(const Expr *E)

Defines the clang::Expr interface and subclasses for C++ expressions.

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

Defines the clang::LangOptions interface.

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 ...

const clang::PrintingPolicy & getPrintingPolicy() const

This represents one expression.

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

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

const LocationContext * getParent() const

It might return null.

const StackFrameContext * getStackFrame() const

void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const

Prints out the call stack in json format.

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

Stmt - This represents one statement.

StmtClass getStmtClass() const

An entry in the environment consists of a Stmt and an LocationContext.

const Stmt * getStmt() const

EnvironmentEntry(const Stmt *s, const LocationContext *L)

const LocationContext * getLocationContext() const

Environment getInitialEnvironment()

Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate)

Bind a symbolic value to the given environment entry.

Environment removeDeadBindings(Environment Env, SymbolReaper &SymReaper, ProgramStateRef state)

An immutable map from EnvironemntEntries to SVals.

SVal getSVal(const EnvironmentEntry &E, SValBuilder &svalBuilder) const

Fetches the current binding of the expression in the Environment.

void printJson(raw_ostream &Out, const ASTContext &Ctx, const LocationContext *LCtx=nullptr, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const

BindingsTy::iterator iterator

MemRegion - The root abstract class for all memory regions.

std::optional< SVal > getConstantVal(const Expr *E)

Returns the value of E, if it can be determined in a non-path-sensitive manner.

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

A utility class that visits the reachable symbols using a custom SymbolVisitor.

bool scan(nonloc::LazyCompoundVal val)

A class responsible for cleaning up unused symbols.

bool isLive(SymbolRef sym)

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

Describes how types, statements, expressions, and declarations should be printed.