/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|*                                                                            *|
|* Interface Declarations                                                     *|
|*                                                                            *|
|* Automatically generated file, do not edit!                                 *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

namespace fir {

/// Interface for operations that create Fortran like variables in order to
///     query about all their Fortran properties.
class FortranVariableOpInterface;

} // namespace fir
namespace fir {

/// An extension of FortranVariableOpInterface for operations that provide
///     information about the physical storage layout of the variable.
///     The operations provide the raw address of the physical storage
///     and the byte offset where the variable begins within the physical
///     storage.
///     The storage is a reference to an array of known size consisting
///     of i8 elements. This is how Flang represents COMMON and EQUIVALENCE
///     storage blocks with the member variables located within the storage
///     at different offsets. The storage offset for a variable must not
///     exceed the storage size. Note that the zero-sized variables
///     may start at the offset that is after the final byte of the storage.
///     When getStorage() returns nullptr, getStorageOffset() must return 0.
///     This means that nothing is known about the physical storage
///     of the variable (beyond the information maybe provided
///     by the concrete operation itself, e.g. fir.declare defines
///     the physical storage of a variable via memref operand,
///     where the variable starts).
class FortranVariableStorageOpInterface;

} // namespace fir
namespace fir {

/// Interface for operations that may produce results that allow accessing
///     objects in memory based on the operands of these operations.
///     For example:
///     ```
///     %0 = fir.convert %x : (!llvm.ptr) -> !fir.llvm_ptr<i32>
///     ```
///     When the result of `fir.convert` is used to access an object in memory,
///     FIR alias analysis may want to pass through `fir.convert` to be able
///     to find the original Fortran object that is being accessed.
///     This interface provides methods that allow discovering information
///     about the accessed object and the characteristics of the resulting
///     "view" of the object, e.g. whether the result and the input
///     access the object from the same location within the object or
///     whether they are offsetted (which may happen, for example, in case of
///     `fir.array_coor` operation).
class FortranObjectViewOpInterface;

} // namespace fir
namespace fir {

/// Interface for operations that create Fortran like variables in order to
///     query about all their Fortran properties.
namespace detail {
struct FortranVariableOpInterfaceInterfaceTraits {
  struct Concept {
    /// The methods defined by the interface.
    mlir::Value (*getBase)(const Concept *impl, ::mlir::Operation *);
    std::optional<fir::FortranVariableFlagsEnum> (*getFortranAttrs)(const Concept *impl, ::mlir::Operation *);
    mlir::Value (*getShape)(const Concept *impl, ::mlir::Operation *);
    mlir::OperandRange (*getExplicitTypeParams)(const Concept *impl, ::mlir::Operation *);
    void (*setFortranAttrs)(const Concept *impl, ::mlir::Operation *, fir::FortranVariableFlagsEnum);
  };
  template<typename ConcreteOp>
  class Model : public Concept {
  public:
    using Interface = fir::FortranVariableOpInterface;
    Model() : Concept{getBase, getFortranAttrs, getShape, getExplicitTypeParams, setFortranAttrs} {}

    static inline mlir::Value getBase(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline mlir::Value getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline mlir::OperandRange getExplicitTypeParams(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline void setFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags);
  };
  template<typename ConcreteOp>
  class FallbackModel : public Concept {
  public:
    using Interface = fir::FortranVariableOpInterface;
    FallbackModel() : Concept{getBase, getFortranAttrs, getShape, getExplicitTypeParams, setFortranAttrs} {}

    static inline mlir::Value getBase(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline mlir::Value getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline mlir::OperandRange getExplicitTypeParams(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline void setFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags);
  };
  template<typename ConcreteModel, typename ConcreteOp>
  class ExternalModel : public FallbackModel<ConcreteModel> {
  public:
    using ConcreteEntity = ConcreteOp;
    mlir::Value getBase(::mlir::Operation *tablegen_opaque_val) const;
    std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs(::mlir::Operation *tablegen_opaque_val) const;
    mlir::Value getShape(::mlir::Operation *tablegen_opaque_val) const;
    mlir::OperandRange getExplicitTypeParams(::mlir::Operation *tablegen_opaque_val) const;
    void setFortranAttrs(::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags) const;
  };
};
template <typename ConcreteOp>
struct FortranVariableOpInterfaceTrait;

} // namespace detail
class FortranVariableOpInterface : public ::mlir::OpInterface<FortranVariableOpInterface, detail::FortranVariableOpInterfaceInterfaceTraits> {
public:
  using ::mlir::OpInterface<FortranVariableOpInterface, detail::FortranVariableOpInterfaceInterfaceTraits>::OpInterface;
  template <typename ConcreteOp>
  struct Trait : public detail::FortranVariableOpInterfaceTrait<ConcreteOp> {};

  /// Get the address produced by the definition
  mlir::Value getBase();

  /// Get Fortran attributes
  std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs();

  /// Get the shape of the variable. May be a null value.
  mlir::Value getShape();

  /// Get explicit type parameters of the variable
  mlir::OperandRange getExplicitTypeParams();

  /// Set Fortran attributes
  void setFortranAttrs(fir::FortranVariableFlagsEnum flags);


    /// Get the sequence type or scalar value type corresponding to this
    /// variable.
    mlir::Type getElementOrSequenceType() {
      mlir::Type type = fir::unwrapPassByRefType(fir::unwrapRefType(getBase().getType()));
      if (auto boxCharType = mlir::dyn_cast<fir::BoxCharType>(type))
        return boxCharType.getEleTy();
      return type;
    }

    /// Get the scalar value type corresponding to this variable.
    mlir::Type getElementType() {
      return fir::unwrapSequenceType(getElementOrSequenceType());
    }

    /// Is the variable an array?
    bool isArray() {
      return mlir::isa<fir::SequenceType>(getElementOrSequenceType());
    }

    /// Return the rank of the entity if it is known at compile time.
    std::optional<unsigned> getRank() {
      if (auto sequenceType =
            mlir::dyn_cast<fir::SequenceType>(getElementOrSequenceType())) {
        if (sequenceType.hasUnknownShape())
          return {};
        return sequenceType.getDimension();
      }
      return 0;
    }

    /// Is this variable a Fortran pointer?
    bool isPointer() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::pointer);
    }

    /// Is this variable a Cray pointer?
    bool isCrayPointer() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::cray_pointer);
    }

    /// Is this variable a Cray pointee?
    bool isCrayPointee() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::cray_pointee);
    }

    /// Is this variable a Fortran allocatable?
    bool isAllocatable() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::allocatable);
    }

    /// Is this variable a Fortran optional?
    bool isOptional() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::optional);
    }

    /// Does this variable have the Fortran CONTIGUOUS attribute?
    /// Note that not having this attribute does not imply the
    /// variable is not contiguous.
    bool hasContiguousAttr() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::contiguous);
    }

    /// Is this a Fortran character variable?
    bool isCharacter() {
      return mlir::isa<fir::CharacterType>(getElementType());
    }

    /// Is this a Fortran character variable with an explicit length?
    bool hasExplicitCharLen() {
      return isCharacter() && !getExplicitTypeParams().empty();
    }

    /// Return the length of explicit length character variable.
    mlir::Value getExplicitCharLen() {
      assert(hasExplicitCharLen() && "must be an explicit length character");
      return getExplicitTypeParams()[0];
    }

    /// Is this variable represented as a fir.box or fir.class value?
    bool isBoxValue() {
      return mlir::isa<fir::BaseBoxType>(getBase().getType());
    }

    /// Is this variable represented as a fir.box or fir.class address?
    bool isBoxAddress() {
      return fir::isBoxAddress(getBase().getType());
    }

    /// Is this variable represented as the value or address of a fir.box or
    /// fir.class?
    bool isBox() {
      return fir::isBoxAddressOrValue(getBase().getType());
    }

    /// Is this variable a Fortran parameter?
    bool isParameter() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::parameter);
    }

    /// Is this a host associated variable?
    bool isHostAssoc() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::host_assoc);
    }

    /// Is this variable a Fortran target?
    bool isTarget() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::target);
    }

    /// Is this variable captured in an internal procedure via Fortran host association?
    bool isCapturedInInternalProcedure() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::internal_assoc);
    }

    /// Is this variable a Fortran intent(in)?
    bool isIntentIn() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::intent_in);
    }

    /// Interface verifier imlementation for declare operations.
    llvm::LogicalResult verifyDeclareLikeOpImpl(mlir::Value memRef);
};

} // namespace fir
namespace fir {

/// An extension of FortranVariableOpInterface for operations that provide
///     information about the physical storage layout of the variable.
///     The operations provide the raw address of the physical storage
///     and the byte offset where the variable begins within the physical
///     storage.
///     The storage is a reference to an array of known size consisting
///     of i8 elements. This is how Flang represents COMMON and EQUIVALENCE
///     storage blocks with the member variables located within the storage
///     at different offsets. The storage offset for a variable must not
///     exceed the storage size. Note that the zero-sized variables
///     may start at the offset that is after the final byte of the storage.
///     When getStorage() returns nullptr, getStorageOffset() must return 0.
///     This means that nothing is known about the physical storage
///     of the variable (beyond the information maybe provided
///     by the concrete operation itself, e.g. fir.declare defines
///     the physical storage of a variable via memref operand,
///     where the variable starts).
namespace detail {
struct FortranVariableStorageOpInterfaceInterfaceTraits {
  struct Concept {
    /// The methods defined by the interface.
    mlir::Value (*getStorage)(const Concept *impl, ::mlir::Operation *);
    std::uint64_t (*getStorageOffset)(const Concept *impl, ::mlir::Operation *);
    /// The base classes of this interface.
    const fir::FortranVariableOpInterface::Concept *implFortranVariableOpInterface = nullptr;

    void initializeInterfaceConcept(::mlir::detail::InterfaceMap &interfaceMap) {
      implFortranVariableOpInterface = interfaceMap.lookup<fir::FortranVariableOpInterface>();
      assert(implFortranVariableOpInterface && "`fir::FortranVariableStorageOpInterface` expected its base interface `fir::FortranVariableOpInterface` to be registered");
    }
  };
  template<typename ConcreteOp>
  class Model : public Concept {
  public:
    using Interface = fir::FortranVariableStorageOpInterface;
    Model() : Concept{getStorage, getStorageOffset} {}

    static inline mlir::Value getStorage(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline std::uint64_t getStorageOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
  };
  template<typename ConcreteOp>
  class FallbackModel : public Concept {
  public:
    using Interface = fir::FortranVariableStorageOpInterface;
    FallbackModel() : Concept{getStorage, getStorageOffset} {}

    static inline mlir::Value getStorage(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
    static inline std::uint64_t getStorageOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
  };
  template<typename ConcreteModel, typename ConcreteOp>
  class ExternalModel : public FallbackModel<ConcreteModel> {
  public:
    using ConcreteEntity = ConcreteOp;
    mlir::Value getStorage(::mlir::Operation *tablegen_opaque_val) const;
    std::uint64_t getStorageOffset(::mlir::Operation *tablegen_opaque_val) const;
  };
};
template <typename ConcreteOp>
struct FortranVariableStorageOpInterfaceTrait;

} // namespace detail
class FortranVariableStorageOpInterface : public ::mlir::OpInterface<FortranVariableStorageOpInterface, detail::FortranVariableStorageOpInterfaceInterfaceTraits> {
public:
  using ::mlir::OpInterface<FortranVariableStorageOpInterface, detail::FortranVariableStorageOpInterfaceInterfaceTraits>::OpInterface;
  template <typename ConcreteOp>
  struct Trait : public detail::FortranVariableStorageOpInterfaceTrait<ConcreteOp> {};

  /// Returns the raw address of the physical storage
  mlir::Value getStorage();

  /// Returns the byte offset where the variable begins within the physical storage
  std::uint64_t getStorageOffset();
  //===----------------------------------------------------------------===//
  // Inherited from fir::FortranVariableOpInterface
  //===----------------------------------------------------------------===//

  operator fir::FortranVariableOpInterface () const {
    if (!*this) return nullptr;
    return fir::FortranVariableOpInterface(*this, getImpl()->implFortranVariableOpInterface);
  }


  /// Get the address produced by the definition
  mlir::Value getBase();

  /// Get Fortran attributes
  std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs();

  /// Get the shape of the variable. May be a null value.
  mlir::Value getShape();

  /// Get explicit type parameters of the variable
  mlir::OperandRange getExplicitTypeParams();

  /// Set Fortran attributes
  void setFortranAttrs(fir::FortranVariableFlagsEnum flags);


    /// Get the sequence type or scalar value type corresponding to this
    /// variable.
    mlir::Type getElementOrSequenceType() {
      mlir::Type type = fir::unwrapPassByRefType(fir::unwrapRefType(getBase().getType()));
      if (auto boxCharType = mlir::dyn_cast<fir::BoxCharType>(type))
        return boxCharType.getEleTy();
      return type;
    }

    /// Get the scalar value type corresponding to this variable.
    mlir::Type getElementType() {
      return fir::unwrapSequenceType(getElementOrSequenceType());
    }

    /// Is the variable an array?
    bool isArray() {
      return mlir::isa<fir::SequenceType>(getElementOrSequenceType());
    }

    /// Return the rank of the entity if it is known at compile time.
    std::optional<unsigned> getRank() {
      if (auto sequenceType =
            mlir::dyn_cast<fir::SequenceType>(getElementOrSequenceType())) {
        if (sequenceType.hasUnknownShape())
          return {};
        return sequenceType.getDimension();
      }
      return 0;
    }

    /// Is this variable a Fortran pointer?
    bool isPointer() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::pointer);
    }

    /// Is this variable a Cray pointer?
    bool isCrayPointer() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::cray_pointer);
    }

    /// Is this variable a Cray pointee?
    bool isCrayPointee() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::cray_pointee);
    }

    /// Is this variable a Fortran allocatable?
    bool isAllocatable() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::allocatable);
    }

    /// Is this variable a Fortran optional?
    bool isOptional() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::optional);
    }

    /// Does this variable have the Fortran CONTIGUOUS attribute?
    /// Note that not having this attribute does not imply the
    /// variable is not contiguous.
    bool hasContiguousAttr() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::contiguous);
    }

    /// Is this a Fortran character variable?
    bool isCharacter() {
      return mlir::isa<fir::CharacterType>(getElementType());
    }

    /// Is this a Fortran character variable with an explicit length?
    bool hasExplicitCharLen() {
      return isCharacter() && !getExplicitTypeParams().empty();
    }

    /// Return the length of explicit length character variable.
    mlir::Value getExplicitCharLen() {
      assert(hasExplicitCharLen() && "must be an explicit length character");
      return getExplicitTypeParams()[0];
    }

    /// Is this variable represented as a fir.box or fir.class value?
    bool isBoxValue() {
      return mlir::isa<fir::BaseBoxType>(getBase().getType());
    }

    /// Is this variable represented as a fir.box or fir.class address?
    bool isBoxAddress() {
      return fir::isBoxAddress(getBase().getType());
    }

    /// Is this variable represented as the value or address of a fir.box or
    /// fir.class?
    bool isBox() {
      return fir::isBoxAddressOrValue(getBase().getType());
    }

    /// Is this variable a Fortran parameter?
    bool isParameter() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::parameter);
    }

    /// Is this a host associated variable?
    bool isHostAssoc() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::host_assoc);
    }

    /// Is this variable a Fortran target?
    bool isTarget() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::target);
    }

    /// Is this variable captured in an internal procedure via Fortran host association?
    bool isCapturedInInternalProcedure() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::internal_assoc);
    }

    /// Is this variable a Fortran intent(in)?
    bool isIntentIn() {
      auto attrs = getFortranAttrs();
      return attrs && bitEnumContainsAny(*attrs,
                        fir::FortranVariableFlagsEnum::intent_in);
    }

    /// Interface verifier imlementation for declare operations.
    llvm::LogicalResult verifyDeclareLikeOpImpl(mlir::Value memRef);
};

} // namespace fir
namespace fir {

/// Interface for operations that may produce results that allow accessing
///     objects in memory based on the operands of these operations.
///     For example:
///     ```
///     %0 = fir.convert %x : (!llvm.ptr) -> !fir.llvm_ptr<i32>
///     ```
///     When the result of `fir.convert` is used to access an object in memory,
///     FIR alias analysis may want to pass through `fir.convert` to be able
///     to find the original Fortran object that is being accessed.
///     This interface provides methods that allow discovering information
///     about the accessed object and the characteristics of the resulting
///     "view" of the object, e.g. whether the result and the input
///     access the object from the same location within the object or
///     whether they are offsetted (which may happen, for example, in case of
///     `fir.array_coor` operation).
namespace detail {
struct FortranObjectViewOpInterfaceInterfaceTraits {
  struct Concept {
    /// The methods defined by the interface.
    ::mlir::Value (*getViewSource)(const Concept *impl, ::mlir::Operation *, ::mlir::OpResult);
    std::optional<std::int64_t> (*getViewOffset)(const Concept *impl, ::mlir::Operation *, ::mlir::OpResult);
  };
  template<typename ConcreteOp>
  class Model : public Concept {
  public:
    using Interface = ::fir::FortranObjectViewOpInterface;
    Model() : Concept{getViewSource, getViewOffset} {}

    static inline ::mlir::Value getViewSource(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView);
    static inline std::optional<std::int64_t> getViewOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView);
  };
  template<typename ConcreteOp>
  class FallbackModel : public Concept {
  public:
    using Interface = ::fir::FortranObjectViewOpInterface;
    FallbackModel() : Concept{getViewSource, getViewOffset} {}

    static inline ::mlir::Value getViewSource(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView);
    static inline std::optional<std::int64_t> getViewOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView);
  };
  template<typename ConcreteModel, typename ConcreteOp>
  class ExternalModel : public FallbackModel<ConcreteModel> {
  public:
    using ConcreteEntity = ConcreteOp;
    ::mlir::Value getViewSource(::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) const;
    std::optional<std::int64_t> getViewOffset(::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) const;
  };
};
template <typename ConcreteOp>
struct FortranObjectViewOpInterfaceTrait;

} // namespace detail
class FortranObjectViewOpInterface : public ::mlir::OpInterface<FortranObjectViewOpInterface, detail::FortranObjectViewOpInterfaceInterfaceTraits> {
public:
  using ::mlir::OpInterface<FortranObjectViewOpInterface, detail::FortranObjectViewOpInterfaceInterfaceTraits>::OpInterface;
  template <typename ConcreteOp>
  struct Trait : public detail::FortranObjectViewOpInterfaceTrait<ConcreteOp> {};

  /// Returns the operand which the given OpResult is based on.
  ::mlir::Value getViewSource(::mlir::OpResult resultView);

  /// Returns the constant offset (in bytes) applied to the corresponding
  /// operand to produce the resulting view.
  /// If it is not possible to identify the constant offset,
  /// the result is nullopt.
  /// Note that the offset may be negative, e.g. when addressing
  /// an array section with a negative stride.
  std::optional<std::int64_t> getViewOffset(::mlir::OpResult resultView);
};

} // namespace fir
namespace fir::detail {

  template <typename ConcreteOp>
  struct FortranVariableOpInterfaceTrait : public ::mlir::OpInterface<FortranVariableOpInterface, detail::FortranVariableOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {

    /// Get the address produced by the definition
    mlir::Value getBase() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getResult();
    }

    /// Get Fortran attributes
    std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getFortran_attrs();
    }

    /// Get the shape of the variable. May be a null value.
    mlir::Value getShape() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getShape();
    }

    /// Get explicit type parameters of the variable
    mlir::OperandRange getExplicitTypeParams() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getTypeparams();
    }

    /// Set Fortran attributes
    void setFortranAttrs(fir::FortranVariableFlagsEnum flags) {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        op.setFortran_attrs(fir::FortranVariableFlagsAttr::get(op->getContext(), flags));
    }
  };

} // namespace fir::detail
namespace fir::detail {

  template <typename ConcreteOp>
  struct FortranVariableStorageOpInterfaceTrait : public ::mlir::OpInterface<FortranVariableStorageOpInterface, detail::FortranVariableStorageOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {

    /// Returns the raw address of the physical storage
    mlir::Value getStorage() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getStorage();
    }

    /// Returns the byte offset where the variable begins within the physical storage
    std::uint64_t getStorageOffset() {
      ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getStorageOffset();
    }
    static ::llvm::LogicalResult verifyTrait(::mlir::Operation *op) {
      return detail::verifyFortranVariableStorageOpInterface(op);
    }
  };

} // namespace fir::detail
namespace fir::detail {

  template <typename ConcreteOp>
  struct FortranObjectViewOpInterfaceTrait : public ::mlir::OpInterface<FortranObjectViewOpInterface, detail::FortranObjectViewOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {

    /// Returns the operand which the given OpResult is based on.
    ::mlir::Value getViewSource(::mlir::OpResult resultView) {
      assert((*static_cast<ConcreteOp *>(this)).getOperation() == resultView.getOwner() &&
               "resultView must be a result of this operation");
        return (*static_cast<ConcreteOp *>(this)).getViewSource(resultView);
    }

    /// Returns the constant offset (in bytes) applied to the corresponding
    /// operand to produce the resulting view.
    /// If it is not possible to identify the constant offset,
    /// the result is nullopt.
    /// Note that the offset may be negative, e.g. when addressing
    /// an array section with a negative stride.
    std::optional<std::int64_t> getViewOffset(::mlir::OpResult resultView) {
      assert((*static_cast<ConcreteOp *>(this)).getOperation() == resultView.getOwner() &&
               "resultView must be a result of this operation");
        return (*static_cast<ConcreteOp *>(this)).getViewOffset(resultView);
    }
  };

} // namespace fir::detail
namespace fir {

template<typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::Model<ConcreteOp>::getBase(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getBase();
}
template<typename ConcreteOp>
std::optional<fir::FortranVariableFlagsEnum> detail::FortranVariableOpInterfaceInterfaceTraits::Model<ConcreteOp>::getFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getFortranAttrs();
}
template<typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::Model<ConcreteOp>::getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getShape();
}
template<typename ConcreteOp>
mlir::OperandRange detail::FortranVariableOpInterfaceInterfaceTraits::Model<ConcreteOp>::getExplicitTypeParams(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getExplicitTypeParams();
}
template<typename ConcreteOp>
void detail::FortranVariableOpInterfaceInterfaceTraits::Model<ConcreteOp>::setFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).setFortranAttrs(flags);
}
template<typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getBase(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getBase(tablegen_opaque_val);
}
template<typename ConcreteOp>
std::optional<fir::FortranVariableFlagsEnum> detail::FortranVariableOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getFortranAttrs(tablegen_opaque_val);
}
template<typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getShape(tablegen_opaque_val);
}
template<typename ConcreteOp>
mlir::OperandRange detail::FortranVariableOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getExplicitTypeParams(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getExplicitTypeParams(tablegen_opaque_val);
}
template<typename ConcreteOp>
void detail::FortranVariableOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::setFortranAttrs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags) {
  return static_cast<const ConcreteOp *>(impl)->setFortranAttrs(tablegen_opaque_val, flags);
}
template<typename ConcreteModel, typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getBase(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getResult();
}
template<typename ConcreteModel, typename ConcreteOp>
std::optional<fir::FortranVariableFlagsEnum> detail::FortranVariableOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getFortranAttrs(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getFortran_attrs();
}
template<typename ConcreteModel, typename ConcreteOp>
mlir::Value detail::FortranVariableOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getShape(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getShape();
}
template<typename ConcreteModel, typename ConcreteOp>
mlir::OperandRange detail::FortranVariableOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getExplicitTypeParams(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getTypeparams();
}
template<typename ConcreteModel, typename ConcreteOp>
void detail::FortranVariableOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::setFortranAttrs(::mlir::Operation *tablegen_opaque_val, fir::FortranVariableFlagsEnum flags) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        op.setFortran_attrs(fir::FortranVariableFlagsAttr::get(op->getContext(), flags));
}

} // namespace fir
namespace fir {

template<typename ConcreteOp>
mlir::Value detail::FortranVariableStorageOpInterfaceInterfaceTraits::Model<ConcreteOp>::getStorage(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getStorage();
}
template<typename ConcreteOp>
std::uint64_t detail::FortranVariableStorageOpInterfaceInterfaceTraits::Model<ConcreteOp>::getStorageOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getStorageOffset();
}
template<typename ConcreteOp>
mlir::Value detail::FortranVariableStorageOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getStorage(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getStorage(tablegen_opaque_val);
}
template<typename ConcreteOp>
std::uint64_t detail::FortranVariableStorageOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getStorageOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
  return static_cast<const ConcreteOp *>(impl)->getStorageOffset(tablegen_opaque_val);
}
template<typename ConcreteModel, typename ConcreteOp>
mlir::Value detail::FortranVariableStorageOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getStorage(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getStorage();
}
template<typename ConcreteModel, typename ConcreteOp>
std::uint64_t detail::FortranVariableStorageOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getStorageOffset(::mlir::Operation *tablegen_opaque_val) const {
ConcreteOp op = mlir::cast<ConcreteOp>(this->getOperation());
        return op.getStorageOffset();
}

} // namespace fir
namespace fir {

template<typename ConcreteOp>
::mlir::Value detail::FortranObjectViewOpInterfaceInterfaceTraits::Model<ConcreteOp>::getViewSource(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getViewSource(resultView);
}
template<typename ConcreteOp>
std::optional<std::int64_t> detail::FortranObjectViewOpInterfaceInterfaceTraits::Model<ConcreteOp>::getViewOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) {
  return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getViewOffset(resultView);
}
template<typename ConcreteOp>
::mlir::Value detail::FortranObjectViewOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getViewSource(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) {
  return static_cast<const ConcreteOp *>(impl)->getViewSource(tablegen_opaque_val, resultView);
}
template<typename ConcreteOp>
std::optional<std::int64_t> detail::FortranObjectViewOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getViewOffset(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) {
  return static_cast<const ConcreteOp *>(impl)->getViewOffset(tablegen_opaque_val, resultView);
}
template<typename ConcreteModel, typename ConcreteOp>
::mlir::Value detail::FortranObjectViewOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getViewSource(::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) const {
assert((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation() == resultView.getOwner() &&
               "resultView must be a result of this operation");
        return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getViewSource(resultView);
}
template<typename ConcreteModel, typename ConcreteOp>
std::optional<std::int64_t> detail::FortranObjectViewOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getViewOffset(::mlir::Operation *tablegen_opaque_val, ::mlir::OpResult resultView) const {
assert((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation() == resultView.getOwner() &&
               "resultView must be a result of this operation");
        return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getViewOffset(resultView);
}

} // namespace fir
