diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f3ff4fe4d39c9..e0be2b7afb4ec 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -732,6 +732,38 @@ class ValueDecl : public NamedDecl { bool isInitCapture() const; /* TO_UPSTREAM(BoundsSafety) ON */ + /// Whether this decl is a dependent count. This returns true for dependent + /// counts with and without dereference: + /// void foo(int *__counted_by(m) p, int m, + /// int *__counted_by(*n) *q, int *n); + /// True for both `m` and `n`. + bool isDependentCount() const; + + /// Whether this decl is a dependent count without a dereference: + /// void foo(int *__counted_by(m) p, int m, + /// int *__counted_by(*n) *q, int *n); + /// True for `m`, but false for `n`. + bool isDependentCountWithoutDeref() const; + + /// Whether this decl is a dependent count with a dereference: + /// void foo(int *__counted_by(m) p, int m, + /// int *__counted_by(*n) *q, int *n); + /// False for `m`, but true for `n`. + bool isDependentCountWithDeref() const; + + /// Whether this decl is a dependent count that is used at least once in a + /// count expression of an inout count-attributed pointer. + /// void foo(int *__counted_by(a) p, int a, + /// int *__counted_by(*b) q, int *b, + /// int *__counted_by(c) *r, int c, + /// int *__counted_by(*d) *s, int *d); + /// True for `c` and `d`, but false for `a` and `b`. + /// void bar(int *__counted_by(count) in_p, + /// int *__counted_by(count) *out_p, + /// int count); + /// True for `count` (because of `out_p`). + bool isDependentCountThatIsUsedInInoutPointer() const; + /// Whether this decl is a dependent parameter referred to by the return type /// that is a bounds-attributed type. bool isDependentParamOfReturnType( diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 22b8d4e1c4f23..01238971ca758 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -2651,6 +2651,10 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isAnyVaListType(ASTContext &) const; bool isDynamicRangePointerType() const; bool isBoundsAttributedType() const; + /// Whether this type is a count-attributed type that is depending on an + /// inout count. True for `__counted_by(*count)`, but false for + /// `__counted_by(len)`. + bool isCountAttributedTypeDependingOnInoutCount() const; bool isValueTerminatedType() const; bool isImplicitlyNullTerminatedType(const ASTContext &) const; /* TO_UPSTREAM(BoundsSafety) OFF */ diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index accfe96c9cdb7..c4d79c0baef0e 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -5502,6 +5502,27 @@ bool ValueDecl::isParameterPack() const { } /* TO_UPSTREAM(BoundsSafety) ON */ +bool ValueDecl::isDependentCount() const { + return hasAttr(); +} + +bool ValueDecl::isDependentCountWithoutDeref() const { + const auto *Att = getAttr(); + return Att && !Att->getIsDeref(); +} + +bool ValueDecl::isDependentCountWithDeref() const { + const auto *Att = getAttr(); + return Att && Att->getIsDeref(); +} + +bool ValueDecl::isDependentCountThatIsUsedInInoutPointer() const { + const auto *Att = getAttr(); + return Att && + std::any_of(Att->dependerLevels_begin(), Att->dependerLevels_end(), + [](unsigned Level) { return Level > 0; }); +} + bool ValueDecl::isDependentParamOfReturnType( const BoundsAttributedType **RetType, const TypeCoupledDeclRefInfo **Info) const { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 08b9b40b3f8a6..e38bb1241ed16 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -829,6 +829,14 @@ bool Type::isBoundsAttributedType() const { return getAs(); } +bool Type::isCountAttributedTypeDependingOnInoutCount() const { + const auto *CAT = getAs(); + return CAT && + std::any_of( + CAT->dependent_decl_begin(), CAT->dependent_decl_end(), + [](const TypeCoupledDeclRefInfo &Info) { return Info.isDeref(); }); +} + bool Type::isValueTerminatedType() const { return getAs(); }