[clang] nonblocking/nonallocating attributes (was: nolock/noalloc) (PR #84983)
Doug Wyatt via cfe-commits
cfe-commits at lists.llvm.org
Wed May 22 08:01:49 PDT 2024
================
@@ -4429,6 +4433,210 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
}
};
+// ------------------------------------------------------------------------------
+
+class Decl;
+class CXXMethodDecl;
+class FunctionEffectSet;
+
+/// Represents an abstract function effect, using just an enumeration describing
+/// its type. Encapsulates its semantic behaviors.
+class FunctionEffect {
+public:
+ /// Identifies the particular effect.
+ enum class Kind : uint8_t {
+ None,
+ NonBlocking,
+ NonAllocating,
+ };
+
+ /// Flags describing some behaviors of the effect.
+ using Flags = unsigned;
+ enum FlagBit : Flags {
+ // 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,
+ Merge // Base method's effects are merged with those of the override.
+ };
+
+private:
+ Kind FKind;
+
+ // Expansion: for hypothetical TCB+types, there could be one Kind for TCB,
+ // then ~16(?) bits "SubKind" to map to a specific named TCB. SubKind would
+ // be considered for uniqueness.
+
+public:
+ FunctionEffect() : FKind(Kind::None) {}
+
+ explicit FunctionEffect(Kind T) : FKind(T) {}
+
+ /// The kind of the effect.
+ Kind kind() const { return FKind; }
+
+ /// Return an opaque integer, as a serializable representation.
+ uint32_t getAsOpaqueValue() const { return llvm::to_underlying(FKind); }
+
+ /// Construct from a serialized representation.
+ static FunctionEffect getFromOpaqueValue(uint32_t V) {
+ return FunctionEffect(static_cast<Kind>(V));
+ }
+
+ /// Flags describing some behaviors of the effect.
+ Flags flags() const {
+ switch (FKind) {
+ case Kind::NonBlocking:
+ return FE_InferrableOnCallees | FE_ExcludeThrow | FE_ExcludeCatch |
+ FE_ExcludeObjCMessageSend | FE_ExcludeStaticLocalVars |
+ FE_ExcludeThreadLocalVars;
+ case Kind::NonAllocating:
+ // Same as NonBlocking, except without FE_ExcludeStaticLocalVars
+ return FE_InferrableOnCallees | FE_ExcludeThrow | FE_ExcludeCatch |
+ FE_ExcludeObjCMessageSend | FE_ExcludeThreadLocalVars;
+ case Kind::None:
+ break;
+ }
+ llvm_unreachable("unknown effect kind");
+ }
+
+ /// The description printed in diagnostics, e.g. 'nonblocking'.
+ StringRef name() const;
+
+ /// Return true if adding or removing the effect as part of a type conversion
+ /// should generate a diagnostic.
+ bool shouldDiagnoseConversion(bool Adding, QualType OldType,
+ const FunctionEffectSet &OldFX,
+ QualType NewType,
+ const FunctionEffectSet &NewFX) const;
+
+ /// Return true if adding or removing the effect in a redeclaration should
+ /// generate a diagnostic.
+ bool shouldDiagnoseRedeclaration(bool Adding, const FunctionDecl &OldFunction,
+ const FunctionEffectSet &OldFX,
+ const FunctionDecl &NewFunction,
+ const FunctionEffectSet &NewFX) const;
+
+ /// Return true if adding or removing the effect in a C++ virtual method
+ /// override should generate a diagnostic.
+ OverrideResult
+ shouldDiagnoseMethodOverride(bool Adding, const CXXMethodDecl &OldMethod,
+ const FunctionEffectSet &OldFX,
+ const CXXMethodDecl &NewMethod,
+ const FunctionEffectSet &NewFX) const;
+
+ /// Return true if the effect is allowed to be inferred on the callee,
+ /// which is either a FunctionDecl or BlockDecl.
+ /// This is only used if the effect has FE_InferrableOnCallees flag set.
+ /// Example: This allows nonblocking(false) to prevent inference for the
+ /// function.
+ bool canInferOnFunction(const Decl &Callee) const;
+
+ // Return false for success. When true is returned for a direct call, then the
+ // FE_InferrableOnCallees flag may trigger inference rather than an immediate
+ // diagnostic. Caller should be assumed to have the effect (it may not have it
+ // explicitly when inferring).
+ bool shouldDiagnoseFunctionCall(bool Direct,
+ const FunctionEffectSet &CalleeFX) const;
+
+ friend bool operator==(const FunctionEffect &LHS, const FunctionEffect &RHS) {
+ return LHS.FKind == RHS.FKind;
+ }
+ friend bool operator!=(const FunctionEffect &LHS, const FunctionEffect &RHS) {
+ return LHS.FKind != RHS.FKind;
+ }
+ friend bool operator<(const FunctionEffect &LHS, const FunctionEffect &RHS) {
+ return LHS.FKind < RHS.FKind;
+ }
+};
+
+/// A value type, representing a set of FunctionEffects. To reduce superfluous
+/// retain/release, however, prefer to pass by reference.
+class FunctionEffectSet {
----------------
dougsonos wrote:
Done
https://github.com/llvm/llvm-project/pull/84983
More information about the cfe-commits
mailing list