@@ -61,6 +61,7 @@ class BTFTypeTagAttr;
61
61
class ExtQuals ;
62
62
class QualType ;
63
63
class ConceptDecl ;
64
+ class ValueDecl ;
64
65
class TagDecl ;
65
66
class TemplateParameterList ;
66
67
class Type ;
@@ -2000,6 +2001,21 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
2000
2001
unsigned NumExpansions;
2001
2002
};
2002
2003
2004
+ class CountAttributedTypeBitfields {
2005
+ friend class CountAttributedType ;
2006
+
2007
+ LLVM_PREFERRED_TYPE (TypeBitfields)
2008
+ unsigned : NumTypeBits;
2009
+
2010
+ static constexpr unsigned NumCoupledDeclsBits = 4 ;
2011
+ unsigned NumCoupledDecls : NumCoupledDeclsBits;
2012
+ LLVM_PREFERRED_TYPE (bool )
2013
+ unsigned CountInBytes : 1 ;
2014
+ LLVM_PREFERRED_TYPE (bool )
2015
+ unsigned OrNull : 1 ;
2016
+ };
2017
+ static_assert (sizeof (CountAttributedTypeBitfields) <= sizeof (unsigned ));
2018
+
2003
2019
union {
2004
2020
TypeBitfields TypeBits;
2005
2021
ArrayTypeBitfields ArrayTypeBits;
@@ -2022,6 +2038,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
2022
2038
DependentTemplateSpecializationTypeBitfields
2023
2039
DependentTemplateSpecializationTypeBits;
2024
2040
PackExpansionTypeBitfields PackExpansionTypeBits;
2041
+ CountAttributedTypeBitfields CountAttributedTypeBits;
2025
2042
};
2026
2043
2027
2044
private:
@@ -2264,6 +2281,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
2264
2281
bool isFunctionProtoType () const { return getAs<FunctionProtoType>(); }
2265
2282
bool isPointerType () const ;
2266
2283
bool isAnyPointerType () const ; // Any C pointer or ObjC object pointer
2284
+ bool isCountAttributedType () const ;
2267
2285
bool isBlockPointerType () const ;
2268
2286
bool isVoidPointerType () const ;
2269
2287
bool isReferenceType () const ;
@@ -2724,6 +2742,14 @@ template <> const TemplateSpecializationType *Type::getAs() const;
2724
2742
// / until it reaches an AttributedType or a non-sugared type.
2725
2743
template <> const AttributedType *Type::getAs () const ;
2726
2744
2745
+ // / This will check for a BoundsAttributedType by removing any existing
2746
+ // / sugar until it reaches an BoundsAttributedType or a non-sugared type.
2747
+ template <> const BoundsAttributedType *Type::getAs () const ;
2748
+
2749
+ // / This will check for a CountAttributedType by removing any existing
2750
+ // / sugar until it reaches an CountAttributedType or a non-sugared type.
2751
+ template <> const CountAttributedType *Type::getAs () const ;
2752
+
2727
2753
// We can do canonical leaf types faster, because we don't have to
2728
2754
// worry about preserving child type decoration.
2729
2755
#define TYPE (Class, Base )
@@ -2922,6 +2948,136 @@ class PointerType : public Type, public llvm::FoldingSetNode {
2922
2948
static bool classof (const Type *T) { return T->getTypeClass () == Pointer; }
2923
2949
};
2924
2950
2951
+ // / [BoundsSafety] Represents information of declarations referenced by the
2952
+ // / arguments of the `counted_by` attribute and the likes.
2953
+ class TypeCoupledDeclRefInfo {
2954
+ public:
2955
+ using BaseTy = llvm::PointerIntPair<ValueDecl *, 1 , unsigned >;
2956
+
2957
+ private:
2958
+ enum {
2959
+ DerefShift = 0 ,
2960
+ DerefMask = 1 ,
2961
+ };
2962
+ BaseTy Data;
2963
+
2964
+ public:
2965
+ // / \p D is to a declaration referenced by the argument of attribute. \p Deref
2966
+ // / indicates whether \p D is referenced as a dereferenced form, e.g., \p
2967
+ // / Deref is true for `*n` in `int *__counted_by(*n)`.
2968
+ TypeCoupledDeclRefInfo (ValueDecl *D = nullptr , bool Deref = false );
2969
+
2970
+ bool isDeref () const ;
2971
+ ValueDecl *getDecl () const ;
2972
+ unsigned getInt () const ;
2973
+ void *getOpaqueValue () const ;
2974
+ bool operator ==(const TypeCoupledDeclRefInfo &Other) const ;
2975
+ void setFromOpaqueValue (void *V);
2976
+ };
2977
+
2978
+ // / [BoundsSafety] Represents a parent type class for CountAttributedType and
2979
+ // / similar sugar types that will be introduced to represent a type with a
2980
+ // / bounds attribute.
2981
+ // /
2982
+ // / Provides a common interface to navigate declarations referred to by the
2983
+ // / bounds expression.
2984
+
2985
+ class BoundsAttributedType : public Type , public llvm ::FoldingSetNode {
2986
+ QualType WrappedTy;
2987
+
2988
+ protected:
2989
+ ArrayRef<TypeCoupledDeclRefInfo> Decls; // stored in trailing objects
2990
+
2991
+ BoundsAttributedType (TypeClass TC, QualType Wrapped, QualType Canon);
2992
+
2993
+ public:
2994
+ bool isSugared () const { return true ; }
2995
+ QualType desugar () const { return WrappedTy; }
2996
+
2997
+ using decl_iterator = const TypeCoupledDeclRefInfo *;
2998
+ using decl_range = llvm::iterator_range<decl_iterator>;
2999
+
3000
+ decl_iterator dependent_decl_begin () const { return Decls.begin (); }
3001
+ decl_iterator dependent_decl_end () const { return Decls.end (); }
3002
+
3003
+ unsigned getNumCoupledDecls () const { return Decls.size (); }
3004
+
3005
+ decl_range dependent_decls () const {
3006
+ return decl_range (dependent_decl_begin (), dependent_decl_end ());
3007
+ }
3008
+
3009
+ ArrayRef<TypeCoupledDeclRefInfo> getCoupledDecls () const {
3010
+ return {dependent_decl_begin (), dependent_decl_end ()};
3011
+ }
3012
+
3013
+ bool referencesFieldDecls () const ;
3014
+
3015
+ static bool classof (const Type *T) {
3016
+ // Currently, only `class CountAttributedType` inherits
3017
+ // `BoundsAttributedType` but the subclass will grow as we add more bounds
3018
+ // annotations.
3019
+ switch (T->getTypeClass ()) {
3020
+ case CountAttributed:
3021
+ return true ;
3022
+ default :
3023
+ return false ;
3024
+ }
3025
+ }
3026
+ };
3027
+
3028
+ // / Represents a sugar type with `__counted_by` or `__sized_by` annotations,
3029
+ // / including their `_or_null` variants.
3030
+ class CountAttributedType final
3031
+ : public BoundsAttributedType,
3032
+ public llvm::TrailingObjects<CountAttributedType,
3033
+ TypeCoupledDeclRefInfo> {
3034
+ friend class ASTContext ;
3035
+
3036
+ Expr *CountExpr;
3037
+ // / \p CountExpr represents the argument of __counted_by or the likes. \p
3038
+ // / CountInBytes indicates that \p CountExpr is a byte count (i.e.,
3039
+ // / __sized_by(_or_null)) \p OrNull means it's an or_null variant (i.e.,
3040
+ // / __counted_by_or_null or __sized_by_or_null) \p CoupledDecls contains the
3041
+ // / list of declarations referenced by \p CountExpr, which the type depends on
3042
+ // / for the bounds information.
3043
+ CountAttributedType (QualType Wrapped, QualType Canon, Expr *CountExpr,
3044
+ bool CountInBytes, bool OrNull,
3045
+ ArrayRef<TypeCoupledDeclRefInfo> CoupledDecls);
3046
+
3047
+ unsigned numTrailingObjects (OverloadToken<TypeCoupledDeclRefInfo>) const {
3048
+ return CountAttributedTypeBits.NumCoupledDecls ;
3049
+ }
3050
+
3051
+ public:
3052
+ enum DynamicCountPointerKind {
3053
+ CountedBy = 0 ,
3054
+ SizedBy,
3055
+ CountedByOrNull,
3056
+ SizedByOrNull,
3057
+ };
3058
+
3059
+ Expr *getCountExpr () const { return CountExpr; }
3060
+ bool isCountInBytes () const { return CountAttributedTypeBits.CountInBytes ; }
3061
+ bool isOrNull () const { return CountAttributedTypeBits.OrNull ; }
3062
+
3063
+ DynamicCountPointerKind getKind () const {
3064
+ if (isOrNull ())
3065
+ return isCountInBytes () ? SizedByOrNull : CountedByOrNull;
3066
+ return isCountInBytes () ? SizedBy : CountedBy;
3067
+ }
3068
+
3069
+ void Profile (llvm::FoldingSetNodeID &ID) {
3070
+ Profile (ID, desugar (), CountExpr, isCountInBytes (), isOrNull ());
3071
+ }
3072
+
3073
+ static void Profile (llvm::FoldingSetNodeID &ID, QualType WrappedTy,
3074
+ Expr *CountExpr, bool CountInBytes, bool Nullable);
3075
+
3076
+ static bool classof (const Type *T) {
3077
+ return T->getTypeClass () == CountAttributed;
3078
+ }
3079
+ };
3080
+
2925
3081
// / Represents a type which was implicitly adjusted by the semantic
2926
3082
// / engine for arbitrary reasons. For example, array and function types can
2927
3083
// / decay, and function types can have their calling conventions adjusted.
0 commit comments