@@ -148,7 +148,7 @@ class AvarBoundsInference {
148
148
// BoundsKey that failed the flow inference.
149
149
std::set<BoundsKey> BKsFailedFlowInference;
150
150
151
- static ABounds *getPreferredBound (const BndsKindMap &BKindMap );
151
+ ABounds *getPreferredBound (BoundsKey BK );
152
152
};
153
153
154
154
// Class that maintains information about potential bounds for
@@ -181,7 +181,8 @@ class AVarBoundsInfo {
181
181
public:
182
182
AVarBoundsInfo ()
183
183
: ProgVarGraph(this ), CtxSensProgVarGraph(this ),
184
- RevCtxSensProgVarGraph (this ), CSBKeyHandler(this ) {
184
+ RevCtxSensProgVarGraph (this ), CSBKeyHandler(this ),
185
+ LowerBoundGraph(this ) {
185
186
BCount = 1 ;
186
187
PVarInfo.clear ();
187
188
InProgramArrPtrBoundsKeys.clear ();
@@ -231,11 +232,9 @@ class AVarBoundsInfo {
231
232
232
233
// Add Assignments between variables. These methods will add edges between
233
234
// corresponding BoundsKeys
234
- bool addAssignment (clang::Decl *L, clang::Decl *R);
235
- bool addAssignment (clang::DeclRefExpr *L, clang::DeclRefExpr *R);
236
235
bool addAssignment (BoundsKey L, BoundsKey R);
237
- bool handlePointerAssignment (clang::Stmt *St , clang::Expr *L, clang::Expr *R ,
238
- ASTContext *C, ConstraintResolver *CR);
236
+ bool handlePointerAssignment (clang::Expr *L , clang::Expr *R, ASTContext *C ,
237
+ ConstraintResolver *CR);
239
238
bool handleAssignment (clang::Expr *L, const CVarSet &LCVars,
240
239
const std::set<BoundsKey> &CSLKeys, clang::Expr *R,
241
240
const CVarSet &RCVars,
@@ -252,11 +251,40 @@ class AVarBoundsInfo {
252
251
// for pointers that has pointer arithmetic performed on them.
253
252
void recordArithmeticOperation (clang::Expr *E, ConstraintResolver *CR);
254
253
255
- // Check if the given bounds key has a pointer arithmetic done on it.
256
- bool hasPointerArithmetic (BoundsKey BK);
254
+ // Check if the given bounds key will need to be duplicated during rewriting
255
+ // to generate a fresh lower bound. This happens when a pointer is not a valid
256
+ // lower bounds due to pointer arithmetic, and lower bounds inference fails to
257
+ // find a consistent lower bound among existing pointers in the source code.
258
+ bool needsFreshLowerBound (BoundsKey BK);
259
+ bool needsFreshLowerBound (ConstraintVariable *CV);
260
+
261
+ // Return true when a lower bound could be inferred for the array pointer
262
+ // corresponding to `BK`. This is the case either when `BK` was not
263
+ // invalidated as lower bound by pointer arithmetic meaning it is it's own
264
+ // lower bound, or when `BK` was invalidated, but a valid lower bound could be
265
+ // inferred.
266
+ bool hasLowerBound (BoundsKey BK);
267
+
268
+ // Record that a pointer cannot be rewritten to use range bounds. This might
269
+ // be due to 3C rewriting limitations (assignments appearing inside macros),
270
+ // or it might be a Checked C limitation (the current style of range bounds
271
+ // can't properly initialized on global variables without error).
272
+ void markIneligibleForFreshLowerBound (BoundsKey BK);
257
273
258
274
// Get the ProgramVar for the provided VarKey.
259
- ProgramVar *getProgramVar (BoundsKey VK);
275
+ // This method can return `nullptr` if there is no corresponding ProgramVar.
276
+ // It's not obvious when a BoundsKey can be expected to have a ProgramVar, so
277
+ // callers should typically check for null.
278
+ ProgramVar *getProgramVar (BoundsKey VK) const ;
279
+
280
+ // Get the Scope of the provided BoundsKey.
281
+ // This method returns nullptr if `getProgramVar(BK)` would return nullptr.
282
+ const ProgramVarScope *getProgramVarScope (BoundsKey BK) const ;
283
+
284
+ // Return true when BoundsKey `To` can be accessed from the scope of `from`.
285
+ // Note that this returns false if either BoundsKey cannot be mapped to a
286
+ // ProgramVar (and therefore can't be mapped to a scope).
287
+ bool isInAccessibleScope (BoundsKey From, BoundsKey To);
260
288
261
289
// Propagate the array bounds information for all array ptrs.
262
290
void performFlowAnalysis (ProgramInfo *PI);
@@ -294,6 +322,13 @@ class AVarBoundsInfo {
294
322
295
323
void addConstantArrayBounds (ProgramInfo &I);
296
324
325
+ // This is the main entry point to start lower bound inference. It populates
326
+ // the map LowerBounds and set NeedFreshLowerBounds with the result of the
327
+ // analysis. LowerBounds is accessed during the rest of bounds inference, so
328
+ // this method must be executed before performFlowAnalysis which handles the
329
+ // majority of the work for length inference.
330
+ void inferLowerBounds (ProgramInfo *PI);
331
+
297
332
private:
298
333
friend class AvarBoundsInference ;
299
334
friend class CtxSensitiveBoundsKeyHandler ;
@@ -315,8 +350,17 @@ class AVarBoundsInfo {
315
350
// Set that contains BoundsKeys of variables which have invalid bounds.
316
351
std::set<BoundsKey> InvalidBounds;
317
352
// These are the bounds key of the pointers that has arithmetic operations
318
- // performed on them.
353
+ // performed on them. These pointers cannot have the standard `count(n)`
354
+ // bounds and instead must use range bounds with an explict lower bound
355
+ // e.g., `bounds(p, p + n)`.
319
356
std::set<BoundsKey> ArrPointersWithArithmetic;
357
+
358
+ // Some pointers, however, cannot be automatically given range bounds. This
359
+ // includes global variables and structure fields. If a pointer is in both the
360
+ // above pointer arithmetic set and this set, then it cannot be assigned any
361
+ // bound.
362
+ std::set<BoundsKey> IneligibleForFreshLowerBound;
363
+
320
364
// Set of BoundsKeys that correspond to pointers.
321
365
std::set<BoundsKey> PointerBoundsKey;
322
366
// Set of BoundsKey that correspond to array pointers.
@@ -342,6 +386,9 @@ class AVarBoundsInfo {
342
386
// BiMap of function keys and BoundsKey for function return values.
343
387
BiMap<std::tuple<std::string, std::string, bool >, BoundsKey> FuncDeclVarMap;
344
388
389
+ PVConstraint *
390
+ getConstraintVariable (const ProgramInfo *PI, BoundsKey BK) const ;
391
+
345
392
// Graph of all program variables.
346
393
AVarGraph ProgVarGraph;
347
394
// Graph that contains only edges from normal BoundsKey to
@@ -356,6 +403,31 @@ class AVarBoundsInfo {
356
403
// Context-sensitive bounds key handler
357
404
CtxSensitiveBoundsKeyHandler CSBKeyHandler;
358
405
406
+ // This graph is used of for determining which pointers are valid lower
407
+ // bounds, and so are eligible for use as their own lower bound (implicitly as
408
+ // a count bounds) or as the lower bound for another pointer in a range bound.
409
+ // It is also used to infer lower bounds for the pointers that are not
410
+ // eligible to be their own lower bound.
411
+ AVarGraph LowerBoundGraph;
412
+ // In the LowerBoundGraph the constant 0 is used to represent the global
413
+ // singleton invalid pointer.
414
+ const BoundsKey InvalidLowerBoundKey = 0 ;
415
+
416
+ // BoundsKeys that that cannot be used as a lower bound. These are used in an
417
+ // update such as `a = a + 1`, or are transitively assigned from such a
418
+ // pointer.
419
+ std::set<BoundsKey> InvalidLowerBounds;
420
+
421
+ // Mapping from pointers to their inferred lower bounds. A pointer maps to
422
+ // itself if it can use a simple count bound. Missing pointers have no valid
423
+ // lower bound, so no length should be inferred during bounds inference.
424
+ std::map<BoundsKey, BoundsKey> LowerBounds;
425
+
426
+ // Some variables have to valid lower bound in the original source code, but
427
+ // we are able to insert a temporary pointer variable to be the lower bound.
428
+ // Keep track of these for special handling during rewriting.
429
+ std::set<BoundsKey> NeedFreshLowerBounds;
430
+
359
431
// BoundsKey helper function: These functions help in getting bounds key from
360
432
// various artifacts.
361
433
bool hasVarKey (PersistentSourceLoc &PSL);
@@ -389,6 +461,31 @@ class AVarBoundsInfo {
389
461
void insertParamKey (ParamDeclType ParamDecl, BoundsKey NK);
390
462
391
463
void dumpBounds ();
464
+
465
+ // Compute which array pointers are not valid lower bounds. This includes any
466
+ // pointers directly updated in pointer arithmetic expression, as well as any
467
+ // pointers transitively assigned to from these pointers. This is computed
468
+ // using essentially the same algorithm as is used for solving the checked
469
+ // type constraint graph.
470
+ void computeInvalidLowerBounds (ProgramInfo *PI);
471
+
472
+ // During lower bound inference it may be necessary to generate temporary
473
+ // pointers to act as lower bounds for arrays that otherwise don't have a
474
+ // consistent lower bound. This method takes a bounds key for an array pointer
475
+ // and returns a fresh bounds key that can be used as the lower bound for the
476
+ // array bounds of that pointer.
477
+ BoundsKey getFreshLowerBound (BoundsKey Arr);
478
+
479
+ // Return true if the scope of the BoundsKey is one in which lower bounds
480
+ // can be inserted. BoundsKeys in context sensitive scope should not get lower
481
+ // bounds. The corresponding non-context-sensitive BoundsKey should instead.
482
+ bool scopeCanHaveLowerBound (BoundsKey BK);
483
+
484
+ // Check if a fresh lower bound can be be inserted by 3C for the pointer
485
+ // corresponding to the bounds key. When a pointer needs a fresh lower bound,
486
+ // it is possible that 3C will not support inserting the new declaration.
487
+ // No array bounds can be inferred for such pointers.
488
+ bool isEligibleForFreshLowerBound (BoundsKey BK);
392
489
};
393
490
394
491
#endif // LLVM_CLANG_3C_AVARBOUNDSINFO_H
0 commit comments