Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/TypeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
21 changes: 21 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5502,6 +5502,27 @@ bool ValueDecl::isParameterPack() const {
}

/* TO_UPSTREAM(BoundsSafety) ON */
bool ValueDecl::isDependentCount() const {
return hasAttr<DependerDeclsAttr>();
}

bool ValueDecl::isDependentCountWithoutDeref() const {
const auto *Att = getAttr<DependerDeclsAttr>();
return Att && !Att->getIsDeref();
}

bool ValueDecl::isDependentCountWithDeref() const {
const auto *Att = getAttr<DependerDeclsAttr>();
return Att && Att->getIsDeref();
}

bool ValueDecl::isDependentCountThatIsUsedInInoutPointer() const {
const auto *Att = getAttr<DependerDeclsAttr>();
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 {
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,14 @@ bool Type::isBoundsAttributedType() const {
return getAs<BoundsAttributedType>();
}

bool Type::isCountAttributedTypeDependingOnInoutCount() const {
const auto *CAT = getAs<CountAttributedType>();
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<ValueTerminatedType>();
}
Expand Down