@@ -186,6 +186,14 @@ template <typename LatticeT> struct DataflowAnalysisState {
186
186
// / the dataflow analysis cannot be performed successfully. Otherwise, calls
187
187
// / `PostVisitCFG` on each CFG element with the final analysis results at that
188
188
// / program point.
189
+ // /
190
+ // / `MaxBlockVisits` caps the number of block visits during analysis. It doesn't
191
+ // / distinguish between repeat visits to the same block and visits to distinct
192
+ // / blocks. This parameter is a backstop to prevent infintite loops, in the case
193
+ // / of bugs in the lattice and/or transfer functions that prevent the analysis
194
+ // / from converging. The default value is essentially arbitrary -- large enough
195
+ // / to accomodate what seems like any reasonable CFG, but still small enough to
196
+ // / limit the cost of hitting the limit.
189
197
template <typename AnalysisT>
190
198
llvm::Expected<std::vector<
191
199
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
@@ -194,7 +202,8 @@ runDataflowAnalysis(
194
202
const Environment &InitEnv,
195
203
std::function<void (const CFGElement &, const DataflowAnalysisState<
196
204
typename AnalysisT::Lattice> &)>
197
- PostVisitCFG = nullptr ) {
205
+ PostVisitCFG = nullptr ,
206
+ std::int32_t MaxBlockVisits = 20'000 ) {
198
207
std::function<void (const CFGElement &,
199
208
const TypeErasedDataflowAnalysisState &)>
200
209
PostVisitCFGClosure = nullptr ;
@@ -212,7 +221,7 @@ runDataflowAnalysis(
212
221
}
213
222
214
223
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis (
215
- CFCtx, Analysis, InitEnv, PostVisitCFGClosure);
224
+ CFCtx, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits );
216
225
if (!TypeErasedBlockStates)
217
226
return TypeErasedBlockStates.takeError ();
218
227
@@ -261,14 +270,23 @@ auto createAnalysis(ASTContext &ASTCtx, Environment &Env)
261
270
// / iterations.
262
271
// / - This limit is still low enough to keep runtimes acceptable (on typical
263
272
// / machines) in cases where we hit the limit.
273
+ // /
274
+ // / `MaxBlockVisits` caps the number of block visits during analysis. It doesn't
275
+ // / distinguish between repeat visits to the same block and visits to distinct
276
+ // / blocks. This parameter is a backstop to prevent infintite loops, in the case
277
+ // / of bugs in the lattice and/or transfer functions that prevent the analysis
278
+ // / from converging. The default value is essentially arbitrary -- large enough
279
+ // / to accomodate what seems like any reasonable CFG, but still small enough to
280
+ // / limit the cost of hitting the limit.
264
281
template <typename AnalysisT, typename Diagnostic>
265
282
llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction (
266
283
const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
267
284
llvm::function_ref<llvm::SmallVector<Diagnostic>(
268
285
const CFGElement &, ASTContext &,
269
286
const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
270
287
Diagnoser,
271
- std::int64_t MaxSATIterations = 1'000'000'000) {
288
+ std::int64_t MaxSATIterations = 1'000'000'000,
289
+ std::int32_t MaxBlockVisits = 20'000) {
272
290
llvm::Expected<ControlFlowContext> Context =
273
291
ControlFlowContext::build (FuncDecl);
274
292
if (!Context)
@@ -293,7 +311,8 @@ llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
293
311
State.Lattice .Value ),
294
312
State.Env ));
295
313
llvm::move (EltDiagnostics, std::back_inserter (Diagnostics));
296
- })
314
+ },
315
+ MaxBlockVisits)
297
316
.takeError ())
298
317
return std::move (Err);
299
318
0 commit comments