/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|*                                                                            *|
|* Enum Utility Declarations                                                  *|
|*                                                                            *|
|* Automatically generated file, do not edit!                                 *|
|* From: FIRAttr.td                                                           *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

namespace fir {
// allowed 32-bit signless integer cases: 0, 1
enum class BoxFieldAttr : uint32_t {
  base_addr = 0,
  derived_type = 1,
};

::std::optional<BoxFieldAttr> symbolizeBoxFieldAttr(uint32_t);
::llvm::StringRef stringifyBoxFieldAttr(BoxFieldAttr);
::std::optional<BoxFieldAttr> symbolizeBoxFieldAttr(::llvm::StringRef);
inline constexpr unsigned getMaxEnumValForBoxFieldAttr() {
  return 1;
}


inline ::llvm::StringRef stringifyEnum(BoxFieldAttr enumValue) {
  return stringifyBoxFieldAttr(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<BoxFieldAttr> symbolizeEnum<BoxFieldAttr>(::llvm::StringRef str) {
  return symbolizeBoxFieldAttr(str);
}

class BoxFieldAttrAttr : public ::mlir::IntegerAttr {
public:
  using ValueType = BoxFieldAttr;
  using ::mlir::IntegerAttr::IntegerAttr;
  static bool classof(::mlir::Attribute attr);
  static BoxFieldAttrAttr get(::mlir::MLIRContext *context, BoxFieldAttr val);
  BoxFieldAttr getValue() const;
};
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<fir::BoxFieldAttr, fir::BoxFieldAttr> {
  template <typename ParserT>
  static FailureOr<fir::BoxFieldAttr> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for allowed 32-bit signless integer cases: 0, 1");

    // Symbolize the keyword.
    if (::std::optional<fir::BoxFieldAttr> attr = fir::symbolizeEnum<fir::BoxFieldAttr>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid allowed 32-bit signless integer cases: 0, 1 specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<fir::BoxFieldAttr>, std::optional<fir::BoxFieldAttr>> {
  template <typename ParserT>
  static FailureOr<std::optional<fir::BoxFieldAttr>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<fir::BoxFieldAttr>{};

    // Symbolize the keyword.
    if (::std::optional<fir::BoxFieldAttr> attr = fir::symbolizeEnum<fir::BoxFieldAttr>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid allowed 32-bit signless integer cases: 0, 1 specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, fir::BoxFieldAttr value) {
  auto valueStr = stringifyEnum(value);
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<fir::BoxFieldAttr> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline fir::BoxFieldAttr getEmptyKey() {
    return static_cast<fir::BoxFieldAttr>(StorageInfo::getEmptyKey());
  }

  static inline fir::BoxFieldAttr getTombstoneKey() {
    return static_cast<fir::BoxFieldAttr>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const fir::BoxFieldAttr &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const fir::BoxFieldAttr &lhs, const fir::BoxFieldAttr &rhs) {
    return lhs == rhs;
  }
};
}

namespace fir {
// Fortran procedure attributes
enum class FortranProcedureFlagsEnum : uint32_t {
  none = 0,
  elemental = 1,
  pure = 2,
  non_recursive = 4,
  simple = 8,
  bind_c = 16,
};

::std::optional<FortranProcedureFlagsEnum> symbolizeFortranProcedureFlagsEnum(uint32_t);
std::string stringifyFortranProcedureFlagsEnum(FortranProcedureFlagsEnum);
::std::optional<FortranProcedureFlagsEnum> symbolizeFortranProcedureFlagsEnum(::llvm::StringRef);

inline constexpr FortranProcedureFlagsEnum operator|(FortranProcedureFlagsEnum a, FortranProcedureFlagsEnum b) {
  return static_cast<FortranProcedureFlagsEnum>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}
inline constexpr FortranProcedureFlagsEnum operator&(FortranProcedureFlagsEnum a, FortranProcedureFlagsEnum b) {
  return static_cast<FortranProcedureFlagsEnum>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
}
inline constexpr FortranProcedureFlagsEnum operator^(FortranProcedureFlagsEnum a, FortranProcedureFlagsEnum b) {
  return static_cast<FortranProcedureFlagsEnum>(static_cast<uint32_t>(a) ^ static_cast<uint32_t>(b));
}
inline constexpr FortranProcedureFlagsEnum operator~(FortranProcedureFlagsEnum bits) {
  // Ensure only bits that can be present in the enum are set
  return static_cast<FortranProcedureFlagsEnum>(~static_cast<uint32_t>(bits) & static_cast<uint32_t>(31u));
}
inline constexpr bool bitEnumContainsAll(FortranProcedureFlagsEnum bits, FortranProcedureFlagsEnum bit) {
  return (bits & bit) == bit;
}
inline constexpr bool bitEnumContainsAny(FortranProcedureFlagsEnum bits, FortranProcedureFlagsEnum bit) {
  return (static_cast<uint32_t>(bits) & static_cast<uint32_t>(bit)) != 0;
}
inline constexpr FortranProcedureFlagsEnum bitEnumClear(FortranProcedureFlagsEnum bits, FortranProcedureFlagsEnum bit) {
  return bits & ~bit;
}
inline constexpr FortranProcedureFlagsEnum bitEnumSet(FortranProcedureFlagsEnum bits, FortranProcedureFlagsEnum bit, /*optional*/bool value=true) {
  return value ? (bits | bit) : bitEnumClear(bits, bit);
}
  
inline std::string stringifyEnum(FortranProcedureFlagsEnum enumValue) {
  return stringifyFortranProcedureFlagsEnum(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<FortranProcedureFlagsEnum> symbolizeEnum<FortranProcedureFlagsEnum>(::llvm::StringRef str) {
  return symbolizeFortranProcedureFlagsEnum(str);
}
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<::fir::FortranProcedureFlagsEnum, ::fir::FortranProcedureFlagsEnum> {
  template <typename ParserT>
  static FailureOr<::fir::FortranProcedureFlagsEnum> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for Fortran procedure attributes");

    // Symbolize the keyword.
    if (::std::optional<::fir::FortranProcedureFlagsEnum> attr = ::fir::symbolizeEnum<::fir::FortranProcedureFlagsEnum>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid Fortran procedure attributes specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<::fir::FortranProcedureFlagsEnum>, std::optional<::fir::FortranProcedureFlagsEnum>> {
  template <typename ParserT>
  static FailureOr<std::optional<::fir::FortranProcedureFlagsEnum>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<::fir::FortranProcedureFlagsEnum>{};

    // Symbolize the keyword.
    if (::std::optional<::fir::FortranProcedureFlagsEnum> attr = ::fir::symbolizeEnum<::fir::FortranProcedureFlagsEnum>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid Fortran procedure attributes specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::fir::FortranProcedureFlagsEnum value) {
  auto valueStr = stringifyEnum(value);
  auto underlyingValue = static_cast<std::make_unsigned_t<::fir::FortranProcedureFlagsEnum>>(value);
  if (underlyingValue && !llvm::has_single_bit(underlyingValue))
    return p << '"' << valueStr << '"';
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<::fir::FortranProcedureFlagsEnum> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline ::fir::FortranProcedureFlagsEnum getEmptyKey() {
    return static_cast<::fir::FortranProcedureFlagsEnum>(StorageInfo::getEmptyKey());
  }

  static inline ::fir::FortranProcedureFlagsEnum getTombstoneKey() {
    return static_cast<::fir::FortranProcedureFlagsEnum>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const ::fir::FortranProcedureFlagsEnum &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const ::fir::FortranProcedureFlagsEnum &lhs, const ::fir::FortranProcedureFlagsEnum &rhs) {
    return lhs == rhs;
  }
};
}

namespace fir {
// Fortran variable attributes
enum class FortranVariableFlagsEnum : uint32_t {
  None = 0,
  allocatable = 1,
  asynchronous = 2,
  bind_c = 4,
  contiguous = 8,
  intent_in = 16,
  intent_inout = 32,
  intent_out = 64,
  optional = 128,
  parameter = 256,
  pointer = 512,
  target = 1024,
  value = 2048,
  fortran_volatile = 4096,
  host_assoc = 8192,
  internal_assoc = 16384,
};

::std::optional<FortranVariableFlagsEnum> symbolizeFortranVariableFlagsEnum(uint32_t);
std::string stringifyFortranVariableFlagsEnum(FortranVariableFlagsEnum);
::std::optional<FortranVariableFlagsEnum> symbolizeFortranVariableFlagsEnum(::llvm::StringRef);

inline constexpr FortranVariableFlagsEnum operator|(FortranVariableFlagsEnum a, FortranVariableFlagsEnum b) {
  return static_cast<FortranVariableFlagsEnum>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}
inline constexpr FortranVariableFlagsEnum operator&(FortranVariableFlagsEnum a, FortranVariableFlagsEnum b) {
  return static_cast<FortranVariableFlagsEnum>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
}
inline constexpr FortranVariableFlagsEnum operator^(FortranVariableFlagsEnum a, FortranVariableFlagsEnum b) {
  return static_cast<FortranVariableFlagsEnum>(static_cast<uint32_t>(a) ^ static_cast<uint32_t>(b));
}
inline constexpr FortranVariableFlagsEnum operator~(FortranVariableFlagsEnum bits) {
  // Ensure only bits that can be present in the enum are set
  return static_cast<FortranVariableFlagsEnum>(~static_cast<uint32_t>(bits) & static_cast<uint32_t>(32767u));
}
inline constexpr bool bitEnumContainsAll(FortranVariableFlagsEnum bits, FortranVariableFlagsEnum bit) {
  return (bits & bit) == bit;
}
inline constexpr bool bitEnumContainsAny(FortranVariableFlagsEnum bits, FortranVariableFlagsEnum bit) {
  return (static_cast<uint32_t>(bits) & static_cast<uint32_t>(bit)) != 0;
}
inline constexpr FortranVariableFlagsEnum bitEnumClear(FortranVariableFlagsEnum bits, FortranVariableFlagsEnum bit) {
  return bits & ~bit;
}
inline constexpr FortranVariableFlagsEnum bitEnumSet(FortranVariableFlagsEnum bits, FortranVariableFlagsEnum bit, /*optional*/bool value=true) {
  return value ? (bits | bit) : bitEnumClear(bits, bit);
}
  
inline std::string stringifyEnum(FortranVariableFlagsEnum enumValue) {
  return stringifyFortranVariableFlagsEnum(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<FortranVariableFlagsEnum> symbolizeEnum<FortranVariableFlagsEnum>(::llvm::StringRef str) {
  return symbolizeFortranVariableFlagsEnum(str);
}

class FortranVariableFlagsEnumAttr : public ::mlir::IntegerAttr {
public:
  using ValueType = FortranVariableFlagsEnum;
  using ::mlir::IntegerAttr::IntegerAttr;
  static bool classof(::mlir::Attribute attr);
  static FortranVariableFlagsEnumAttr get(::mlir::MLIRContext *context, FortranVariableFlagsEnum val);
  FortranVariableFlagsEnum getValue() const;
};
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<::fir::FortranVariableFlagsEnum, ::fir::FortranVariableFlagsEnum> {
  template <typename ParserT>
  static FailureOr<::fir::FortranVariableFlagsEnum> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for Fortran variable attributes");

    // Symbolize the keyword.
    if (::std::optional<::fir::FortranVariableFlagsEnum> attr = ::fir::symbolizeEnum<::fir::FortranVariableFlagsEnum>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid Fortran variable attributes specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<::fir::FortranVariableFlagsEnum>, std::optional<::fir::FortranVariableFlagsEnum>> {
  template <typename ParserT>
  static FailureOr<std::optional<::fir::FortranVariableFlagsEnum>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<::fir::FortranVariableFlagsEnum>{};

    // Symbolize the keyword.
    if (::std::optional<::fir::FortranVariableFlagsEnum> attr = ::fir::symbolizeEnum<::fir::FortranVariableFlagsEnum>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid Fortran variable attributes specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::fir::FortranVariableFlagsEnum value) {
  auto valueStr = stringifyEnum(value);
  auto underlyingValue = static_cast<std::make_unsigned_t<::fir::FortranVariableFlagsEnum>>(value);
  if (underlyingValue && !llvm::has_single_bit(underlyingValue))
    return p << '"' << valueStr << '"';
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<::fir::FortranVariableFlagsEnum> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline ::fir::FortranVariableFlagsEnum getEmptyKey() {
    return static_cast<::fir::FortranVariableFlagsEnum>(StorageInfo::getEmptyKey());
  }

  static inline ::fir::FortranVariableFlagsEnum getTombstoneKey() {
    return static_cast<::fir::FortranVariableFlagsEnum>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const ::fir::FortranVariableFlagsEnum &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const ::fir::FortranVariableFlagsEnum &lhs, const ::fir::FortranVariableFlagsEnum &rhs) {
    return lhs == rhs;
  }
};
}

namespace fir {
// Flang location kind
enum class LocationKind : uint32_t {
  Base = 0,
  Inclusion = 1,
};

::std::optional<LocationKind> symbolizeLocationKind(uint32_t);
::llvm::StringRef stringifyLocationKind(LocationKind);
::std::optional<LocationKind> symbolizeLocationKind(::llvm::StringRef);
inline constexpr unsigned getMaxEnumValForLocationKind() {
  return 1;
}


inline ::llvm::StringRef stringifyEnum(LocationKind enumValue) {
  return stringifyLocationKind(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<LocationKind> symbolizeEnum<LocationKind>(::llvm::StringRef str) {
  return symbolizeLocationKind(str);
}
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<::fir::LocationKind, ::fir::LocationKind> {
  template <typename ParserT>
  static FailureOr<::fir::LocationKind> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for Flang location kind");

    // Symbolize the keyword.
    if (::std::optional<::fir::LocationKind> attr = ::fir::symbolizeEnum<::fir::LocationKind>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid Flang location kind specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<::fir::LocationKind>, std::optional<::fir::LocationKind>> {
  template <typename ParserT>
  static FailureOr<std::optional<::fir::LocationKind>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<::fir::LocationKind>{};

    // Symbolize the keyword.
    if (::std::optional<::fir::LocationKind> attr = ::fir::symbolizeEnum<::fir::LocationKind>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid Flang location kind specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::fir::LocationKind value) {
  auto valueStr = stringifyEnum(value);
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<::fir::LocationKind> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline ::fir::LocationKind getEmptyKey() {
    return static_cast<::fir::LocationKind>(StorageInfo::getEmptyKey());
  }

  static inline ::fir::LocationKind getTombstoneKey() {
    return static_cast<::fir::LocationKind>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const ::fir::LocationKind &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const ::fir::LocationKind &lhs, const ::fir::LocationKind &rhs) {
    return lhs == rhs;
  }
};
}

namespace fir {
// Describes how to modify lower bounds
enum class LowerBoundModifierAttribute : uint32_t {
  Preserve = 0,
  SetToOnes = 1,
  SetToZeroes = 2,
};

::std::optional<LowerBoundModifierAttribute> symbolizeLowerBoundModifierAttribute(uint32_t);
::llvm::StringRef stringifyLowerBoundModifierAttribute(LowerBoundModifierAttribute);
::std::optional<LowerBoundModifierAttribute> symbolizeLowerBoundModifierAttribute(::llvm::StringRef);
inline constexpr unsigned getMaxEnumValForLowerBoundModifierAttribute() {
  return 2;
}


inline ::llvm::StringRef stringifyEnum(LowerBoundModifierAttribute enumValue) {
  return stringifyLowerBoundModifierAttribute(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<LowerBoundModifierAttribute> symbolizeEnum<LowerBoundModifierAttribute>(::llvm::StringRef str) {
  return symbolizeLowerBoundModifierAttribute(str);
}

class LowerBoundModifierAttributeAttr : public ::mlir::IntegerAttr {
public:
  using ValueType = LowerBoundModifierAttribute;
  using ::mlir::IntegerAttr::IntegerAttr;
  static bool classof(::mlir::Attribute attr);
  static LowerBoundModifierAttributeAttr get(::mlir::MLIRContext *context, LowerBoundModifierAttribute val);
  LowerBoundModifierAttribute getValue() const;
};
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<::fir::LowerBoundModifierAttribute, ::fir::LowerBoundModifierAttribute> {
  template <typename ParserT>
  static FailureOr<::fir::LowerBoundModifierAttribute> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for Describes how to modify lower bounds");

    // Symbolize the keyword.
    if (::std::optional<::fir::LowerBoundModifierAttribute> attr = ::fir::symbolizeEnum<::fir::LowerBoundModifierAttribute>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid Describes how to modify lower bounds specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<::fir::LowerBoundModifierAttribute>, std::optional<::fir::LowerBoundModifierAttribute>> {
  template <typename ParserT>
  static FailureOr<std::optional<::fir::LowerBoundModifierAttribute>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<::fir::LowerBoundModifierAttribute>{};

    // Symbolize the keyword.
    if (::std::optional<::fir::LowerBoundModifierAttribute> attr = ::fir::symbolizeEnum<::fir::LowerBoundModifierAttribute>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid Describes how to modify lower bounds specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::fir::LowerBoundModifierAttribute value) {
  auto valueStr = stringifyEnum(value);
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<::fir::LowerBoundModifierAttribute> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline ::fir::LowerBoundModifierAttribute getEmptyKey() {
    return static_cast<::fir::LowerBoundModifierAttribute>(StorageInfo::getEmptyKey());
  }

  static inline ::fir::LowerBoundModifierAttribute getTombstoneKey() {
    return static_cast<::fir::LowerBoundModifierAttribute>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const ::fir::LowerBoundModifierAttribute &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const ::fir::LowerBoundModifierAttribute &lhs, const ::fir::LowerBoundModifierAttribute &rhs) {
    return lhs == rhs;
  }
};
}

namespace fir {
// intrinsic operations and functions supported by DO CONCURRENT REDUCE
enum class ReduceOperationEnum : uint32_t {
  Add = 1,
  Multiply = 2,
  AND = 4,
  OR = 8,
  EQV = 16,
  NEQV = 32,
  MAX = 64,
  MIN = 128,
  IAND = 256,
  IOR = 512,
  EIOR = 1024,
};

::std::optional<ReduceOperationEnum> symbolizeReduceOperationEnum(uint32_t);
std::string stringifyReduceOperationEnum(ReduceOperationEnum);
::std::optional<ReduceOperationEnum> symbolizeReduceOperationEnum(::llvm::StringRef);

inline constexpr ReduceOperationEnum operator|(ReduceOperationEnum a, ReduceOperationEnum b) {
  return static_cast<ReduceOperationEnum>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}
inline constexpr ReduceOperationEnum operator&(ReduceOperationEnum a, ReduceOperationEnum b) {
  return static_cast<ReduceOperationEnum>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
}
inline constexpr ReduceOperationEnum operator^(ReduceOperationEnum a, ReduceOperationEnum b) {
  return static_cast<ReduceOperationEnum>(static_cast<uint32_t>(a) ^ static_cast<uint32_t>(b));
}
inline constexpr ReduceOperationEnum operator~(ReduceOperationEnum bits) {
  // Ensure only bits that can be present in the enum are set
  return static_cast<ReduceOperationEnum>(~static_cast<uint32_t>(bits) & static_cast<uint32_t>(2047u));
}
inline constexpr bool bitEnumContainsAll(ReduceOperationEnum bits, ReduceOperationEnum bit) {
  return (bits & bit) == bit;
}
inline constexpr bool bitEnumContainsAny(ReduceOperationEnum bits, ReduceOperationEnum bit) {
  return (static_cast<uint32_t>(bits) & static_cast<uint32_t>(bit)) != 0;
}
inline constexpr ReduceOperationEnum bitEnumClear(ReduceOperationEnum bits, ReduceOperationEnum bit) {
  return bits & ~bit;
}
inline constexpr ReduceOperationEnum bitEnumSet(ReduceOperationEnum bits, ReduceOperationEnum bit, /*optional*/bool value=true) {
  return value ? (bits | bit) : bitEnumClear(bits, bit);
}
  
inline std::string stringifyEnum(ReduceOperationEnum enumValue) {
  return stringifyReduceOperationEnum(enumValue);
}

template <typename EnumType>
::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);

template <>
inline ::std::optional<ReduceOperationEnum> symbolizeEnum<ReduceOperationEnum>(::llvm::StringRef str) {
  return symbolizeReduceOperationEnum(str);
}

class ReduceOperationEnumAttr : public ::mlir::IntegerAttr {
public:
  using ValueType = ReduceOperationEnum;
  using ::mlir::IntegerAttr::IntegerAttr;
  static bool classof(::mlir::Attribute attr);
  static ReduceOperationEnumAttr get(::mlir::MLIRContext *context, ReduceOperationEnum val);
  ReduceOperationEnum getValue() const;
};
} // namespace fir

namespace mlir {
template <typename T, typename>
struct FieldParser;

template<>
struct FieldParser<::fir::ReduceOperationEnum, ::fir::ReduceOperationEnum> {
  template <typename ParserT>
  static FailureOr<::fir::ReduceOperationEnum> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return parser.emitError(loc, "expected keyword for intrinsic operations and functions supported by DO CONCURRENT REDUCE");

    // Symbolize the keyword.
    if (::std::optional<::fir::ReduceOperationEnum> attr = ::fir::symbolizeEnum<::fir::ReduceOperationEnum>(enumKeyword))
      return *attr;
    return parser.emitError(loc, "invalid intrinsic operations and functions supported by DO CONCURRENT REDUCE specification: ") << enumKeyword;
  }
};

/// Support for std::optional, useful in attribute/type definition where the enum is
/// used as:
///
///    let parameters = (ins OptionalParameter<"std::optional<TheEnumName>">:$value);
template<>
struct FieldParser<std::optional<::fir::ReduceOperationEnum>, std::optional<::fir::ReduceOperationEnum>> {
  template <typename ParserT>
  static FailureOr<std::optional<::fir::ReduceOperationEnum>> parse(ParserT &parser) {
    // Parse the keyword/string containing the enum.
    std::string enumKeyword;
    auto loc = parser.getCurrentLocation();
    if (failed(parser.parseOptionalKeywordOrString(&enumKeyword)))
      return std::optional<::fir::ReduceOperationEnum>{};

    // Symbolize the keyword.
    if (::std::optional<::fir::ReduceOperationEnum> attr = ::fir::symbolizeEnum<::fir::ReduceOperationEnum>(enumKeyword))
      return attr;
    return parser.emitError(loc, "invalid intrinsic operations and functions supported by DO CONCURRENT REDUCE specification: ") << enumKeyword;
  }
};
} // namespace mlir

namespace llvm {
inline ::llvm::raw_ostream &operator<<(::llvm::raw_ostream &p, ::fir::ReduceOperationEnum value) {
  auto valueStr = stringifyEnum(value);
  auto underlyingValue = static_cast<std::make_unsigned_t<::fir::ReduceOperationEnum>>(value);
  if (underlyingValue && !llvm::has_single_bit(underlyingValue))
    return p << '"' << valueStr << '"';
  return p << valueStr;
}
} // namespace llvm

namespace llvm {
template<> struct DenseMapInfo<::fir::ReduceOperationEnum> {
  using StorageInfo = ::llvm::DenseMapInfo<uint32_t>;

  static inline ::fir::ReduceOperationEnum getEmptyKey() {
    return static_cast<::fir::ReduceOperationEnum>(StorageInfo::getEmptyKey());
  }

  static inline ::fir::ReduceOperationEnum getTombstoneKey() {
    return static_cast<::fir::ReduceOperationEnum>(StorageInfo::getTombstoneKey());
  }

  static unsigned getHashValue(const ::fir::ReduceOperationEnum &val) {
    return StorageInfo::getHashValue(static_cast<uint32_t>(val));
  }

  static bool isEqual(const ::fir::ReduceOperationEnum &lhs, const ::fir::ReduceOperationEnum &rhs) {
    return lhs == rhs;
  }
};
}

