@@ -300,6 +300,72 @@ inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
300300 return !(LHS == RHS);
301301}
302302
303+ /* TO_UPSTREAM(BoundsSafety) ON */
304+ class BoundsSafetyInfo {
305+ public:
306+ enum class BoundsSafetyKind {
307+ CountedBy = 0 ,
308+ CountedByOrNull,
309+ SizedBy,
310+ SizedByOrNull,
311+ EndedBy,
312+ };
313+
314+ private:
315+ // / Whether this property has been audited for nullability.
316+ LLVM_PREFERRED_TYPE (bool )
317+ unsigned KindAudited : 1 ;
318+
319+ // / The kind of nullability for this property. Only valid if the nullability
320+ // / has been audited.
321+ LLVM_PREFERRED_TYPE (BoundsSafetyKind)
322+ unsigned Kind : 3 ;
323+
324+ LLVM_PREFERRED_TYPE (bool )
325+ unsigned LevelAudited : 1 ;
326+
327+ unsigned Level : 3 ;
328+
329+ public:
330+ std::string ExternalBounds;
331+
332+ BoundsSafetyInfo ()
333+ : KindAudited(false ), Kind(0 ), LevelAudited(false ), Level(0 ),
334+ ExternalBounds (" " ) {}
335+
336+ std::optional<BoundsSafetyKind> getKind () const {
337+ return KindAudited ? std::optional<BoundsSafetyKind>(
338+ static_cast <BoundsSafetyKind>(Kind))
339+ : std::nullopt ;
340+ }
341+
342+ void setKindAudited (BoundsSafetyKind kind) {
343+ KindAudited = true ;
344+ Kind = static_cast <unsigned >(kind);
345+ }
346+
347+ std::optional<unsigned > getLevel () const {
348+ return LevelAudited ? std::optional<unsigned >(Level) : std::nullopt ;
349+ }
350+
351+ void setLevelAudited (unsigned level) {
352+ LevelAudited = true ;
353+ Level = level;
354+ }
355+
356+ friend bool operator ==(const BoundsSafetyInfo &, const BoundsSafetyInfo &);
357+
358+ LLVM_DUMP_METHOD void dump (llvm::raw_ostream &OS) const ;
359+ };
360+
361+ inline bool operator ==(const BoundsSafetyInfo &LHS,
362+ const BoundsSafetyInfo &RHS) {
363+ return LHS.KindAudited == RHS.KindAudited && LHS.Kind == RHS.Kind &&
364+ LHS.LevelAudited == RHS.LevelAudited && LHS.Level == RHS.Level &&
365+ LHS.ExternalBounds == RHS.ExternalBounds ;
366+ }
367+ /* TO_UPSTREAM(BoundsSafety) OFF */
368+
303369// / API notes for a variable/property.
304370class VariableInfo : public CommonEntityInfo {
305371 // / Whether this property has been audited for nullability.
@@ -439,10 +505,14 @@ class ParamInfo : public VariableInfo {
439505 unsigned RawRetainCountConvention : 3 ;
440506
441507public:
508+ /* TO_UPSTREAM(BoundsSafety) ON */
509+ std::optional<BoundsSafetyInfo> BoundsSafety;
510+ /* TO_UPSTREAM(BoundsSafety) OFF */
511+
442512 ParamInfo ()
443513 : NoEscapeSpecified(false ), NoEscape(false ),
444514 LifetimeboundSpecified (false ), Lifetimebound(false ),
445- RawRetainCountConvention() {}
515+ RawRetainCountConvention(), BoundsSafety(std:: nullopt ) {}
446516
447517 std::optional<bool > isNoEscape () const {
448518 return NoEscapeSpecified ? std::optional<bool >(NoEscape) : std::nullopt ;
@@ -488,6 +558,11 @@ class ParamInfo : public VariableInfo {
488558 if (!RawRetainCountConvention)
489559 RawRetainCountConvention = RHS.RawRetainCountConvention ;
490560
561+ /* TO_UPSTREAM(BoundsSafety) ON */
562+ if (!BoundsSafety)
563+ BoundsSafety = RHS.BoundsSafety ;
564+ /* TO_UPSTREAM(BoundsSafety) OFF */
565+
491566 return *this ;
492567 }
493568
@@ -502,7 +577,10 @@ inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
502577 LHS.NoEscape == RHS.NoEscape &&
503578 LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified &&
504579 LHS.Lifetimebound == RHS.Lifetimebound &&
505- LHS.RawRetainCountConvention == RHS.RawRetainCountConvention ;
580+ LHS.RawRetainCountConvention == RHS.RawRetainCountConvention &&
581+ /* TO_UPSTREAM(BoundsSafety) ON */
582+ LHS.BoundsSafety == RHS.BoundsSafety ;
583+ /* TO_UPSTREAM(BoundsSafety) OFF */
506584}
507585
508586inline bool operator !=(const ParamInfo &LHS, const ParamInfo &RHS) {
0 commit comments