4949#include " llvm/Support/PointerLikeTypeTraits.h"
5050#include " llvm/Support/TrailingObjects.h"
5151#include " llvm/Support/type_traits.h"
52+ #include < bitset>
5253#include < cassert>
5354#include < cstddef>
5455#include < cstdint>
@@ -119,6 +120,8 @@ class EnumDecl;
119120class Expr ;
120121class ExtQualsTypeCommonBase ;
121122class FunctionDecl ;
123+ class FunctionEffectsRef ;
124+ class FunctionEffectKindSet ;
122125class FunctionEffectSet ;
123126class IdentifierInfo ;
124127class NamedDecl ;
@@ -4712,12 +4715,13 @@ class FunctionEffect {
47124715public:
47134716 // / Identifies the particular effect.
47144717 enum class Kind : uint8_t {
4715- None = 0 ,
4716- NonBlocking = 1 ,
4717- NonAllocating = 2 ,
4718- Blocking = 3 ,
4719- Allocating = 4
4718+ NonBlocking ,
4719+ NonAllocating ,
4720+ Blocking ,
4721+ Allocating ,
4722+ Last = Allocating
47204723 };
4724+ constexpr static size_t KindCount = static_cast <size_t >(Kind::Last) + 1 ;
47214725
47224726 // / Flags describing some behaviors of the effect.
47234727 using Flags = unsigned ;
@@ -4743,8 +4747,6 @@ class FunctionEffect {
47434747 // be considered for uniqueness.
47444748
47454749public:
4746- FunctionEffect () : FKind(Kind::None) {}
4747-
47484750 explicit FunctionEffect (Kind K) : FKind(K) {}
47494751
47504752 // / The kind of the effect.
@@ -4773,35 +4775,43 @@ class FunctionEffect {
47734775 case Kind::Blocking:
47744776 case Kind::Allocating:
47754777 return 0 ;
4776- case Kind::None:
4777- break ;
47784778 }
47794779 llvm_unreachable (" unknown effect kind" );
47804780 }
47814781
47824782 // / The description printed in diagnostics, e.g. 'nonblocking'.
47834783 StringRef name () const ;
47844784
4785- // / Return true if the effect is allowed to be inferred on the callee,
4786- // / which is either a FunctionDecl or BlockDecl.
4785+ friend raw_ostream &operator <<(raw_ostream &OS,
4786+ const FunctionEffect &Effect) {
4787+ OS << Effect.name ();
4788+ return OS;
4789+ }
4790+
4791+ // / Determine whether the effect is allowed to be inferred on the callee,
4792+ // / which is either a FunctionDecl or BlockDecl. If the returned optional
4793+ // / is empty, inference is permitted; otherwise it holds the effect which
4794+ // / blocked inference.
47874795 // / Example: This allows nonblocking(false) to prevent inference for the
47884796 // / function.
4789- bool canInferOnFunction (const Decl &Callee) const ;
4797+ std::optional<FunctionEffect>
4798+ effectProhibitingInference (const Decl &Callee,
4799+ FunctionEffectKindSet CalleeFX) const ;
47904800
47914801 // Return false for success. When true is returned for a direct call, then the
47924802 // FE_InferrableOnCallees flag may trigger inference rather than an immediate
47934803 // diagnostic. Caller should be assumed to have the effect (it may not have it
47944804 // explicitly when inferring).
47954805 bool shouldDiagnoseFunctionCall (bool Direct,
4796- ArrayRef<FunctionEffect> CalleeFX) const ;
4806+ FunctionEffectKindSet CalleeFX) const ;
47974807
4798- friend bool operator ==(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4808+ friend bool operator ==(FunctionEffect LHS, FunctionEffect RHS) {
47994809 return LHS.FKind == RHS.FKind ;
48004810 }
4801- friend bool operator !=(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4811+ friend bool operator !=(FunctionEffect LHS, FunctionEffect RHS) {
48024812 return !(LHS == RHS);
48034813 }
4804- friend bool operator <(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4814+ friend bool operator <(FunctionEffect LHS, FunctionEffect RHS) {
48054815 return LHS.FKind < RHS.FKind ;
48064816 }
48074817};
@@ -4829,13 +4839,14 @@ struct FunctionEffectWithCondition {
48294839 FunctionEffect Effect;
48304840 EffectConditionExpr Cond;
48314841
4832- FunctionEffectWithCondition () = default ;
4833- FunctionEffectWithCondition (const FunctionEffect &E,
4834- const EffectConditionExpr &C)
4842+ FunctionEffectWithCondition (FunctionEffect E, const EffectConditionExpr &C)
48354843 : Effect(E), Cond(C) {}
48364844
48374845 // / Return a textual description of the effect, and its condition, if any.
48384846 std::string description () const ;
4847+
4848+ friend raw_ostream &operator <<(raw_ostream &OS,
4849+ const FunctionEffectWithCondition &CFE);
48394850};
48404851
48414852// / Support iteration in parallel through a pair of FunctionEffect and
@@ -4940,6 +4951,85 @@ class FunctionEffectsRef {
49404951 void dump (llvm::raw_ostream &OS) const ;
49414952};
49424953
4954+ // / A mutable set of FunctionEffect::Kind.
4955+ class FunctionEffectKindSet {
4956+ // For now this only needs to be a bitmap.
4957+ constexpr static size_t EndBitPos = FunctionEffect::KindCount;
4958+ using KindBitsT = std::bitset<EndBitPos>;
4959+
4960+ KindBitsT KindBits{};
4961+
4962+ explicit FunctionEffectKindSet (KindBitsT KB) : KindBits(KB) {}
4963+
4964+ // Functions to translate between an effect kind, starting at 1, and a
4965+ // position in the bitset.
4966+
4967+ constexpr static size_t kindToPos (FunctionEffect::Kind K) {
4968+ return static_cast <size_t >(K);
4969+ }
4970+
4971+ constexpr static FunctionEffect::Kind posToKind (size_t Pos) {
4972+ return static_cast <FunctionEffect::Kind>(Pos);
4973+ }
4974+
4975+ // Iterates through the bits which are set.
4976+ class iterator {
4977+ const FunctionEffectKindSet *Outer = nullptr ;
4978+ size_t Idx = 0 ;
4979+
4980+ // If Idx does not reference a set bit, advance it until it does,
4981+ // or until it reaches EndBitPos.
4982+ void advanceToNextSetBit () {
4983+ while (Idx < EndBitPos && !Outer->KindBits .test (Idx))
4984+ ++Idx;
4985+ }
4986+
4987+ public:
4988+ iterator ();
4989+ iterator (const FunctionEffectKindSet &O, size_t I) : Outer(&O), Idx(I) {
4990+ advanceToNextSetBit ();
4991+ }
4992+ bool operator ==(const iterator &Other) const { return Idx == Other.Idx ; }
4993+ bool operator !=(const iterator &Other) const { return Idx != Other.Idx ; }
4994+
4995+ iterator operator ++() {
4996+ ++Idx;
4997+ advanceToNextSetBit ();
4998+ return *this ;
4999+ }
5000+
5001+ FunctionEffect operator *() const {
5002+ assert (Idx < EndBitPos && " Dereference of end iterator" );
5003+ return FunctionEffect (posToKind (Idx));
5004+ }
5005+ };
5006+
5007+ public:
5008+ FunctionEffectKindSet () = default ;
5009+ explicit FunctionEffectKindSet (FunctionEffectsRef FX) { insert (FX); }
5010+
5011+ iterator begin () const { return iterator (*this , 0 ); }
5012+ iterator end () const { return iterator (*this , EndBitPos); }
5013+
5014+ void insert (FunctionEffect Effect) { KindBits.set (kindToPos (Effect.kind ())); }
5015+ void insert (FunctionEffectsRef FX) {
5016+ for (FunctionEffect Item : FX.effects ())
5017+ insert (Item);
5018+ }
5019+ void insert (FunctionEffectKindSet Set) { KindBits |= Set.KindBits ; }
5020+
5021+ bool empty () const { return KindBits.none (); }
5022+ bool contains (const FunctionEffect::Kind EK) const {
5023+ return KindBits.test (kindToPos (EK));
5024+ }
5025+ void dump (llvm::raw_ostream &OS) const ;
5026+
5027+ static FunctionEffectKindSet difference (FunctionEffectKindSet LHS,
5028+ FunctionEffectKindSet RHS) {
5029+ return FunctionEffectKindSet (LHS.KindBits & ~RHS.KindBits );
5030+ }
5031+ };
5032+
49435033// / A mutable set of FunctionEffects and possibly conditions attached to them.
49445034// / Used to compare and merge effects on declarations.
49455035// /
0 commit comments