4848#include " llvm/Support/PointerLikeTypeTraits.h"
4949#include " llvm/Support/TrailingObjects.h"
5050#include " llvm/Support/type_traits.h"
51+ #include < bitset>
5152#include < cassert>
5253#include < cstddef>
5354#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 ;
@@ -4695,12 +4698,13 @@ class FunctionEffect {
46954698public:
46964699 // / Identifies the particular effect.
46974700 enum class Kind : uint8_t {
4698- None = 0 ,
4699- NonBlocking = 1 ,
4700- NonAllocating = 2 ,
4701- Blocking = 3 ,
4702- Allocating = 4
4701+ NonBlocking ,
4702+ NonAllocating ,
4703+ Blocking ,
4704+ Allocating ,
4705+ Last = Allocating
47034706 };
4707+ constexpr static size_t KindCount = static_cast <size_t >(Kind::Last) + 1 ;
47044708
47054709 // / Flags describing some behaviors of the effect.
47064710 using Flags = unsigned ;
@@ -4726,8 +4730,6 @@ class FunctionEffect {
47264730 // be considered for uniqueness.
47274731
47284732public:
4729- FunctionEffect () : FKind(Kind::None) {}
4730-
47314733 explicit FunctionEffect (Kind K) : FKind(K) {}
47324734
47334735 // / The kind of the effect.
@@ -4756,35 +4758,43 @@ class FunctionEffect {
47564758 case Kind::Blocking:
47574759 case Kind::Allocating:
47584760 return 0 ;
4759- case Kind::None:
4760- break ;
47614761 }
47624762 llvm_unreachable (" unknown effect kind" );
47634763 }
47644764
47654765 // / The description printed in diagnostics, e.g. 'nonblocking'.
47664766 StringRef name () const ;
47674767
4768- // / Return true if the effect is allowed to be inferred on the callee,
4769- // / which is either a FunctionDecl or BlockDecl.
4768+ friend raw_ostream &operator <<(raw_ostream &OS,
4769+ const FunctionEffect &Effect) {
4770+ OS << Effect.name ();
4771+ return OS;
4772+ }
4773+
4774+ // / Determine whether the effect is allowed to be inferred on the callee,
4775+ // / which is either a FunctionDecl or BlockDecl. If the returned optional
4776+ // / is empty, inference is permitted; otherwise it holds the effect which
4777+ // / blocked inference.
47704778 // / Example: This allows nonblocking(false) to prevent inference for the
47714779 // / function.
4772- bool canInferOnFunction (const Decl &Callee) const ;
4780+ std::optional<FunctionEffect>
4781+ effectProhibitingInference (const Decl &Callee,
4782+ FunctionEffectKindSet CalleeFX) const ;
47734783
47744784 // Return false for success. When true is returned for a direct call, then the
47754785 // FE_InferrableOnCallees flag may trigger inference rather than an immediate
47764786 // diagnostic. Caller should be assumed to have the effect (it may not have it
47774787 // explicitly when inferring).
47784788 bool shouldDiagnoseFunctionCall (bool Direct,
4779- ArrayRef<FunctionEffect> CalleeFX) const ;
4789+ FunctionEffectKindSet CalleeFX) const ;
47804790
4781- friend bool operator ==(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4791+ friend bool operator ==(FunctionEffect LHS, FunctionEffect RHS) {
47824792 return LHS.FKind == RHS.FKind ;
47834793 }
4784- friend bool operator !=(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4794+ friend bool operator !=(FunctionEffect LHS, FunctionEffect RHS) {
47854795 return !(LHS == RHS);
47864796 }
4787- friend bool operator <(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4797+ friend bool operator <(FunctionEffect LHS, FunctionEffect RHS) {
47884798 return LHS.FKind < RHS.FKind ;
47894799 }
47904800};
@@ -4812,13 +4822,14 @@ struct FunctionEffectWithCondition {
48124822 FunctionEffect Effect;
48134823 EffectConditionExpr Cond;
48144824
4815- FunctionEffectWithCondition () = default ;
4816- FunctionEffectWithCondition (const FunctionEffect &E,
4817- const EffectConditionExpr &C)
4825+ FunctionEffectWithCondition (FunctionEffect E, const EffectConditionExpr &C)
48184826 : Effect(E), Cond(C) {}
48194827
48204828 // / Return a textual description of the effect, and its condition, if any.
48214829 std::string description () const ;
4830+
4831+ friend raw_ostream &operator <<(raw_ostream &OS,
4832+ const FunctionEffectWithCondition &CFE);
48224833};
48234834
48244835// / Support iteration in parallel through a pair of FunctionEffect and
@@ -4923,6 +4934,85 @@ class FunctionEffectsRef {
49234934 void dump (llvm::raw_ostream &OS) const ;
49244935};
49254936
4937+ // / A mutable set of FunctionEffect::Kind.
4938+ class FunctionEffectKindSet {
4939+ // For now this only needs to be a bitmap.
4940+ constexpr static size_t EndBitPos = FunctionEffect::KindCount;
4941+ using KindBitsT = std::bitset<EndBitPos>;
4942+
4943+ KindBitsT KindBits{};
4944+
4945+ explicit FunctionEffectKindSet (KindBitsT KB) : KindBits(KB) {}
4946+
4947+ // Functions to translate between an effect kind, starting at 1, and a
4948+ // position in the bitset.
4949+
4950+ constexpr static size_t kindToPos (FunctionEffect::Kind K) {
4951+ return static_cast <size_t >(K);
4952+ }
4953+
4954+ constexpr static FunctionEffect::Kind posToKind (size_t Pos) {
4955+ return static_cast <FunctionEffect::Kind>(Pos);
4956+ }
4957+
4958+ // Iterates through the bits which are set.
4959+ class iterator {
4960+ const FunctionEffectKindSet *Outer = nullptr ;
4961+ size_t Idx = 0 ;
4962+
4963+ // If Idx does not reference a set bit, advance it until it does,
4964+ // or until it reaches EndBitPos.
4965+ void advanceToNextSetBit () {
4966+ while (Idx < EndBitPos && !Outer->KindBits .test (Idx))
4967+ ++Idx;
4968+ }
4969+
4970+ public:
4971+ iterator ();
4972+ iterator (const FunctionEffectKindSet &O, size_t I) : Outer(&O), Idx(I) {
4973+ advanceToNextSetBit ();
4974+ }
4975+ bool operator ==(const iterator &Other) const { return Idx == Other.Idx ; }
4976+ bool operator !=(const iterator &Other) const { return Idx != Other.Idx ; }
4977+
4978+ iterator operator ++() {
4979+ ++Idx;
4980+ advanceToNextSetBit ();
4981+ return *this ;
4982+ }
4983+
4984+ FunctionEffect operator *() const {
4985+ assert (Idx < EndBitPos && " Dereference of end iterator" );
4986+ return FunctionEffect (posToKind (Idx));
4987+ }
4988+ };
4989+
4990+ public:
4991+ FunctionEffectKindSet () = default ;
4992+ explicit FunctionEffectKindSet (FunctionEffectsRef FX) { insert (FX); }
4993+
4994+ iterator begin () const { return iterator (*this , 0 ); }
4995+ iterator end () const { return iterator (*this , EndBitPos); }
4996+
4997+ void insert (FunctionEffect Effect) { KindBits.set (kindToPos (Effect.kind ())); }
4998+ void insert (FunctionEffectsRef FX) {
4999+ for (FunctionEffect Item : FX.effects ())
5000+ insert (Item);
5001+ }
5002+ void insert (FunctionEffectKindSet Set) { KindBits |= Set.KindBits ; }
5003+
5004+ bool empty () const { return KindBits.none (); }
5005+ bool contains (const FunctionEffect::Kind EK) const {
5006+ return KindBits.test (kindToPos (EK));
5007+ }
5008+ void dump (llvm::raw_ostream &OS) const ;
5009+
5010+ static FunctionEffectKindSet difference (FunctionEffectKindSet LHS,
5011+ FunctionEffectKindSet RHS) {
5012+ return FunctionEffectKindSet (LHS.KindBits & ~RHS.KindBits );
5013+ }
5014+ };
5015+
49265016// / A mutable set of FunctionEffects and possibly conditions attached to them.
49275017// / Used to compare and merge effects on declarations.
49285018// /
0 commit comments