Index: flang/include/flang/Common/enum-class.h =================================================================== --- /dev/null +++ flang/include/flang/Common/enum-class.h @@ -0,0 +1,60 @@ +//===-- include/flang/Common/enum-class.h -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// The macro +// ENUM_CLASS(className, enum1, enum2, ..., enumN) +// defines +// enum class className { enum1, enum2, ... , enumN }; +// as well as the introspective utilities +// static constexpr std::size_t className_enumSize{N}; +// static inline const std::string &EnumToString(className); + +#ifndef FORTRAN_COMMON_ENUM_CLASS_H_ +#define FORTRAN_COMMON_ENUM_CLASS_H_ + +#include +#include + +namespace Fortran::common { + +constexpr std::size_t CountEnumNames(const char *p) { + std::size_t n{0}; + for (; *p; ++p) { + if (*p == ',') { + ++n; + } + } + return n ? n + 1 : 0; +} + +template +constexpr std::array EnumNames(const char *p) { + std::array result{""}; + std::size_t at{0}; + for (; *p; ++p) { + if (*p == ',') { + ++at; + } else if (*p != ' ') { + result[at] += *p; + } + } + return result; +} + +#define ENUM_CLASS(NAME, ...) \ + enum class NAME { __VA_ARGS__ }; \ + [[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \ + ::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \ + [[maybe_unused]] static inline const std::string &EnumToString(NAME e) { \ + static const auto names{ \ + ::Fortran::common::EnumNames(#__VA_ARGS__)}; \ + return names[static_cast(e)]; \ + } + +} // namespace Fortran::common +#endif // FORTRAN_COMMON_ENUM_CLASS_H_ Index: flang/include/flang/Common/idioms.h =================================================================== --- flang/include/flang/Common/idioms.h +++ flang/include/flang/Common/idioms.h @@ -23,6 +23,7 @@ #error g++ >= 7.2 is required #endif +#include "enum-class.h" #include "visit.h" #include #include @@ -125,32 +126,6 @@ const std::size_t value; }; -#define ENUM_CLASS(NAME, ...) \ - enum class NAME { __VA_ARGS__ }; \ - [[maybe_unused]] static constexpr std::size_t NAME##_enumSize{[] { \ - enum { __VA_ARGS__ }; \ - return Fortran::common::ListItemCount{__VA_ARGS__}.value; \ - }()}; \ - struct NAME##_struct { \ - NAME##_struct(const NAME##_struct &) = delete; \ - NAME##_struct &operator=(const NAME##_struct &) = delete; \ - static NAME##_struct &instance() { \ - static NAME##_struct s; \ - return s; \ - } \ - std::array _enumNames; \ -\ - private: \ - NAME##_struct() { \ - Fortran::common::BuildIndexToString( \ - #__VA_ARGS__, _enumNames.data(), NAME##_enumSize); \ - } \ - ~NAME##_struct() {} \ - }; \ - [[maybe_unused]] static inline const std::string &EnumToString(NAME e) { \ - return NAME##_struct::instance()._enumNames[static_cast(e)]; \ - } - // Check that a pointer is non-null and dereference it #define DEREF(p) Fortran::common::Deref(p, __FILE__, __LINE__) Index: flang/lib/Common/idioms.cpp =================================================================== --- flang/lib/Common/idioms.cpp +++ flang/lib/Common/idioms.cpp @@ -10,7 +10,6 @@ #include #include #include -#include namespace Fortran::common { @@ -24,22 +23,4 @@ std::abort(); } -// Converts the comma separated list of enumerators into tokens which are then -// stored into the provided array of strings. This is intended for use from the -// expansion of ENUM_CLASS. -void BuildIndexToString( - const char *commaSeparated, std::string enumNames[], int enumSize) { - std::string input(commaSeparated); - std::regex reg("\\s*,\\s*"); - - std::sregex_token_iterator iter(input.begin(), input.end(), reg, -1); - std::sregex_token_iterator end; - int index = 0; - while (iter != end) { - enumNames[index] = *iter; - iter++; - index++; - } - CHECK(index == enumSize); -} } // namespace Fortran::common