[clang] nonblocking/nonallocating attributes (was: nolock/noalloc) (PR #84983)

Doug Wyatt via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 10 09:44:15 PDT 2024


================
@@ -4429,6 +4433,218 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
   }
 };
 
+// ------------------------------------------------------------------------------
+
+// TODO: Should FunctionEffect be located elsewhere, where Decl is not
+// forward-declared?
+class Decl;
+class CXXMethodDecl;
+class FunctionEffectSet;
+class TypeSourceInfo;
+
+/// Represents an abstract function effect.
+class FunctionEffect {
+public:
+  /// Identifies the particular type of effect.
+  enum class Type {
+    None = 0,
+    NonBlocking,
+    NonAllocating,
+  };
+
+  /// Flags describing behaviors of the effect.
+  // (Why not a struct with bitfields? There's one function that would like to
+  // test a caller-specified bit. There are some potential optimizations that
+  // would OR together the bits of multiple effects.)
+  using Flags = unsigned;
+  enum FlagBit : unsigned {
+    // Can verification inspect callees' implementations? (e.g. nonblocking:
+    // yes, tcb+types: no)
+    FE_InferrableOnCallees = 0x1,
+
+    // Language constructs which effects can diagnose as disallowed.
+    FE_ExcludeThrow = 0x2,
+    FE_ExcludeCatch = 0x4,
+    FE_ExcludeObjCMessageSend = 0x8,
+    FE_ExcludeStaticLocalVars = 0x10,
+    FE_ExcludeThreadLocalVars = 0x20
+  };
+
+  /// Describes the result of effects differing between a base class's virtual
+  /// method and an overriding method in a subclass.
+  enum class OverrideResult {
+    Ignore,
+    Warn,
+    Propagate // Base method's effects are merged with those of the override.
+  };
+
+private:
+  // For uniqueness, currently only Type_ is significant.
+
+  LLVM_PREFERRED_TYPE(Type)
+  unsigned Type_ : 2;
+  Flags Flags_ : 8; // A constant function of Type but cached here.
+
+  // Expansion: for hypothetical TCB+types, there could be one Type for TCB,
+  // then ~16(?) bits "Subtype" to map to a specific named TCB. Subtype would
+  // be considered for uniqueness.
+
+  // Since this struct is serialized as if it were a uint32_t, it's important
+  // to pad and explicitly zero the extra bits.
+  [[maybe_unused]] unsigned Padding : 22;
+
+public:
+  using CalleeDeclOrType =
+      llvm::PointerUnion<const Decl *, const FunctionProtoType *>;
+
+  FunctionEffect() : Type_(unsigned(Type::None)), Flags_(0), Padding(0) {}
+
+  explicit FunctionEffect(Type T);
+
+  /// The type of the effect.
+  Type type() const { return Type(Type_); }
+
+  /// Flags describing behaviors of the effect.
+  Flags flags() const { return Flags_; }
+
+  /// The description printed in diagnostics, e.g. 'nonblocking'.
+  StringRef name() const;
+
+  /// A hashable representation.
+  uint32_t opaqueRepr() const { return Type_ | (Flags_ << 2u); }
+
+  /// Return true if adding or removing the effect as part of a type conversion
+  /// should generate a diagnostic.
+  bool diagnoseConversion(bool Adding, QualType OldType,
+                          FunctionEffectSet OldFX, QualType NewType,
+                          FunctionEffectSet NewFX) const;
----------------
dougsonos wrote:

I think this is a consequence of trying to abstract the concept of an effect, and hide the differences that make one effect different from another. You might remember that the original implementation had effects as basically an object with a vtable.

https://github.com/llvm/llvm-project/pull/84983


More information about the cfe-commits mailing list