[flang-commits] [flang] bcba39a - [flang] Restore ENUM_CLASS() to be compilation-time code
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Dec 2 09:55:58 PST 2022
Author: Peter Klausler
Date: 2022-12-02T09:55:45-08:00
New Revision: bcba39a56fd4e1debe3854d564c3e03bf0a50ee6
URL: https://github.com/llvm/llvm-project/commit/bcba39a56fd4e1debe3854d564c3e03bf0a50ee6
DIFF: https://github.com/llvm/llvm-project/commit/bcba39a56fd4e1debe3854d564c3e03bf0a50ee6.diff
LOG: [flang] Restore ENUM_CLASS() to be compilation-time code
Rework some recent changes to the ENUM_CLASS() macro so that
all of the construction of enumerator-to-name string mapping
data structures is again performed at compilation time.
Differential Revision: https://reviews.llvm.org/D137859
Added:
flang/include/flang/Common/enum-class.h
Modified:
flang/include/flang/Common/enum-set.h
flang/include/flang/Common/idioms.h
flang/include/flang/Evaluate/type.h
flang/include/flang/Parser/characters.h
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/message.h
flang/lib/Common/idioms.cpp
flang/lib/Evaluate/characteristics.cpp
flang/lib/Lower/IO.cpp
flang/lib/Parser/message.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/attr.cpp
flang/lib/Semantics/expression.cpp
flang/lib/Semantics/mod-file.cpp
flang/lib/Semantics/symbol.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Common/enum-class.h b/flang/include/flang/Common/enum-class.h
new file mode 100644
index 0000000000000..8077520938b31
--- /dev/null
+++ b/flang/include/flang/Common/enum-class.h
@@ -0,0 +1,73 @@
+//===-- 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 <array>
+#include <string>
+
+namespace Fortran::common {
+
+constexpr std::size_t CountEnumNames(const char *p) {
+ std::size_t n{0};
+ std::size_t any{0};
+ for (; *p; ++p) {
+ if (*p == ',') {
+ n += any;
+ any = 0;
+ } else if (*p != ' ') {
+ any = 1;
+ }
+ }
+ return n + any;
+}
+
+template <std::size_t ITEMS>
+constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
+ std::array<std::string_view, ITEMS> result{""};
+ std::size_t at{0};
+ const char *start{nullptr};
+ for (; *p; ++p) {
+ if (*p == ',' || *p == ' ') {
+ if (start) {
+ result[at++] =
+ std::string_view{start, static_cast<std::size_t>(p - start)};
+ start = nullptr;
+ }
+ } else if (!start) {
+ start = p;
+ }
+ }
+ if (start) {
+ result[at] = std::string_view{start, static_cast<std::size_t>(p - start)};
+ }
+ 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 std::string_view EnumToString(NAME e) { \
+ static const constexpr char vaArgs[]{#__VA_ARGS__}; \
+ static const constexpr auto names{ \
+ ::Fortran::common::EnumNames<NAME##_enumSize>(vaArgs)}; \
+ return names[static_cast<std::size_t>(e)]; \
+ }
+
+} // namespace Fortran::common
+#endif // FORTRAN_COMMON_ENUM_CLASS_H_
diff --git a/flang/include/flang/Common/enum-set.h b/flang/include/flang/Common/enum-set.h
index 3b0229104d9f3..5290b76debee8 100644
--- a/flang/include/flang/Common/enum-set.h
+++ b/flang/include/flang/Common/enum-set.h
@@ -207,7 +207,7 @@ template <typename ENUM, std::size_t BITS> class EnumSet {
template <typename STREAM>
STREAM &Dump(
- STREAM &o, const std::string &EnumToString(enumerationType)) const {
+ STREAM &o, std::string_view EnumToString(enumerationType)) const {
char sep{'{'};
IterateOverMembers([&](auto e) {
o << sep << EnumToString(e);
diff --git a/flang/include/flang/Common/idioms.h b/flang/include/flang/Common/idioms.h
index e23ea2c9bda59..7695ebb47dbba 100644
--- a/flang/include/flang/Common/idioms.h
+++ b/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 <array>
#include <functional>
@@ -125,32 +126,6 @@ template <typename A> struct ListItemCount {
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<std::string, NAME##_enumSize> _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<int>(e)]; \
- }
-
// Check that a pointer is non-null and dereference it
#define DEREF(p) Fortran::common::Deref(p, __FILE__, __LINE__)
diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h
index 47ab714c03970..6ebf54be5ba49 100644
--- a/flang/include/flang/Evaluate/type.h
+++ b/flang/include/flang/Evaluate/type.h
@@ -373,7 +373,7 @@ template <TypeCategory CATEGORY> struct SomeKind {
static constexpr TypeCategory category{CATEGORY};
constexpr bool operator==(const SomeKind &) const { return true; }
static std::string AsFortran() {
- return "Some"s + common::EnumToString(category);
+ return "Some"s + std::string{common::EnumToString(category)};
}
};
diff --git a/flang/include/flang/Parser/characters.h b/flang/include/flang/Parser/characters.h
index 120560625da29..1a7d395be2bf7 100644
--- a/flang/include/flang/Parser/characters.h
+++ b/flang/include/flang/Parser/characters.h
@@ -65,7 +65,7 @@ inline constexpr char ToLowerCaseLetter(char &&ch) {
return IsUpperCaseLetter(ch) ? ch - 'A' + 'a' : ch;
}
-inline std::string ToLowerCaseLetters(const std::string &str) {
+inline std::string ToLowerCaseLetters(std::string_view str) {
std::string lowered{str};
for (char &ch : lowered) {
ch = ToLowerCaseLetter(ch);
@@ -81,7 +81,7 @@ inline constexpr char ToUpperCaseLetter(char &&ch) {
return IsLowerCaseLetter(ch) ? ch - 'a' + 'A' : ch;
}
-inline std::string ToUpperCaseLetters(const std::string &str) {
+inline std::string ToUpperCaseLetters(std::string_view str) {
std::string raised{str};
for (char &ch : raised) {
ch = ToUpperCaseLetter(ch);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 66ab5dd6d0237..f96632f3064b6 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -37,7 +37,7 @@ class ParseTreeDumper {
static constexpr const char *GetNodeName(const T &) { return N; }
#define NODE_ENUM(T, E) \
static std::string GetNodeName(const T::E &x) { \
- return #E " = "s + T::EnumToString(x); \
+ return #E " = "s + std::string{T::EnumToString(x)}; \
}
#define NODE(T1, T2) NODE_NAME(T1::T2, #T2)
NODE_NAME(bool, "bool")
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 5ff5b98dba840..0659e04d51df0 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -96,9 +96,9 @@ constexpr MessageFixedText operator""_en_US(const char str[], std::size_t n) {
// The construction of a MessageFormattedText uses a MessageFixedText
// as a vsnprintf() formatting string that is applied to the
-// following arguments. CharBlock and std::string argument
-// values are also supported; they are automatically converted into
-// char pointers that are suitable for '%s' formatting.
+// following arguments. CharBlock, std::string, and std::string_view
+// argument values are also supported; they are automatically converted
+// into char pointers that are suitable for '%s' formatting.
class MessageFormattedText {
public:
template <typename... A>
@@ -128,10 +128,6 @@ class MessageFormattedText {
static_assert(!std::is_class_v<std::decay_t<A>>);
return x;
}
- template <typename A> A Convert(A &x) {
- static_assert(!std::is_class_v<std::decay_t<A>>);
- return x;
- }
template <typename A> common::IfNoLvalue<A, A> Convert(A &&x) {
static_assert(!std::is_class_v<std::decay_t<A>>);
return std::move(x);
@@ -139,8 +135,9 @@ class MessageFormattedText {
const char *Convert(const char *s) { return s; }
const char *Convert(char *s) { return s; }
const char *Convert(const std::string &);
- const char *Convert(std::string &);
const char *Convert(std::string &&);
+ const char *Convert(const std::string_view &);
+ const char *Convert(std::string_view &&);
const char *Convert(CharBlock);
std::intmax_t Convert(std::int64_t x) { return x; }
std::uintmax_t Convert(std::uint64_t x) { return x; }
diff --git a/flang/lib/Common/idioms.cpp b/flang/lib/Common/idioms.cpp
index 95aebd1ec80a4..536a5c2e5479d 100644
--- a/flang/lib/Common/idioms.cpp
+++ b/flang/lib/Common/idioms.cpp
@@ -10,7 +10,6 @@
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
-#include <regex>
namespace Fortran::common {
@@ -24,22 +23,4 @@ namespace Fortran::common {
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
diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index 1795751fbf045..25a427914b5cb 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -1000,7 +1000,7 @@ bool Procedure::IsCompatibleWith(const Procedure &actual, std::string *whyNot,
auto sep{": "s};
*whyNot = "incompatible procedure attributes";
diff erences.IterateOverMembers([&](Attr x) {
- *whyNot += sep + EnumToString(x);
+ *whyNot += sep + std::string{EnumToString(x)};
sep = ", ";
});
}
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 4b08b06e013d3..317bd5d9597d6 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -2091,10 +2091,10 @@ mlir::Value genInquireSpec<Fortran::parser::InquireSpec::CharVar>(
builder.createConvert(loc, specFuncTy.getInput(0), cookie),
builder.createIntegerConstant(
loc, specFuncTy.getInput(1),
- Fortran::runtime::io::HashInquiryKeyword(
+ Fortran::runtime::io::HashInquiryKeyword(std::string{
Fortran::parser::InquireSpec::CharVar::EnumToString(
- std::get<Fortran::parser::InquireSpec::CharVar::Kind>(var.t))
- .c_str())),
+ std::get<Fortran::parser::InquireSpec::CharVar::Kind>(var.t))}
+ .c_str())),
builder.createConvert(loc, specFuncTy.getInput(2), fir::getBase(str)),
builder.createConvert(loc, specFuncTy.getInput(3), fir::getLen(str))};
return builder.create<fir::CallOp>(loc, specFunc, args).getResult(0);
@@ -2128,10 +2128,10 @@ mlir::Value genInquireSpec<Fortran::parser::InquireSpec::IntVar>(
builder.createConvert(loc, specFuncTy.getInput(0), cookie),
builder.createIntegerConstant(
loc, specFuncTy.getInput(1),
- Fortran::runtime::io::HashInquiryKeyword(
+ Fortran::runtime::io::HashInquiryKeyword(std::string{
Fortran::parser::InquireSpec::IntVar::EnumToString(
- std::get<Fortran::parser::InquireSpec::IntVar::Kind>(var.t))
- .c_str())),
+ std::get<Fortran::parser::InquireSpec::IntVar::Kind>(var.t))}
+ .c_str())),
builder.createConvert(loc, specFuncTy.getInput(2), addr),
builder.createConvert(loc, specFuncTy.getInput(3), kind)};
return builder.create<fir::CallOp>(loc, specFunc, args).getResult(0);
@@ -2165,9 +2165,9 @@ mlir::Value genInquireSpec<Fortran::parser::InquireSpec::LogVar>(
else
args.push_back(builder.createIntegerConstant(
loc, specFuncTy.getInput(1),
- Fortran::runtime::io::HashInquiryKeyword(
- Fortran::parser::InquireSpec::LogVar::EnumToString(logVarKind)
- .c_str())));
+ Fortran::runtime::io::HashInquiryKeyword(std::string{
+ Fortran::parser::InquireSpec::LogVar::EnumToString(logVarKind)}
+ .c_str())));
args.push_back(builder.createConvert(loc, specFuncTy.getInput(2), addr));
auto call = builder.create<fir::CallOp>(loc, specFunc, args);
boolRefToLogical(loc, builder, addr);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index d729c8464bbce..a56337d65e5f3 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -70,13 +70,18 @@ const char *MessageFormattedText::Convert(const std::string &s) {
return conversions_.front().c_str();
}
-const char *MessageFormattedText::Convert(std::string &s) {
+const char *MessageFormattedText::Convert(std::string &&s) {
+ conversions_.emplace_front(std::move(s));
+ return conversions_.front().c_str();
+}
+
+const char *MessageFormattedText::Convert(const std::string_view &s) {
conversions_.emplace_front(s);
return conversions_.front().c_str();
}
-const char *MessageFormattedText::Convert(std::string &&s) {
- conversions_.emplace_front(std::move(s));
+const char *MessageFormattedText::Convert(std::string_view &&s) {
+ conversions_.emplace_front(s);
return conversions_.front().c_str();
}
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 9c7990845350f..a8fb6676ada3e 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2621,6 +2621,7 @@ class UnparseVisitor {
void PutKeywordLetter(char);
void Word(const char *);
void Word(const std::string &);
+ void Word(const std::string_view &);
void Indent() { indent_ += indentationAmount_; }
void Outdent() {
CHECK(indent_ >= indentationAmount_);
@@ -2777,6 +2778,12 @@ void UnparseVisitor::Word(const char *str) {
void UnparseVisitor::Word(const std::string &str) { Word(str.c_str()); }
+void UnparseVisitor::Word(const std::string_view &str) {
+ for (std::size_t j{0}; j < str.length(); ++j) {
+ PutKeywordLetter(str[j]);
+ }
+}
+
template <typename A>
void Unparse(llvm::raw_ostream &out, const A &root, Encoding encoding,
bool capitalizeKeywords, bool backslashEscapes,
diff --git a/flang/lib/Semantics/attr.cpp b/flang/lib/Semantics/attr.cpp
index b9b0f327352da..a447672c39cc2 100644
--- a/flang/lib/Semantics/attr.cpp
+++ b/flang/lib/Semantics/attr.cpp
@@ -30,7 +30,7 @@ std::string AttrToString(Attr attr) {
case Attr::INTENT_OUT:
return "INTENT(OUT)";
default:
- return EnumToString(attr);
+ return std::string{EnumToString(attr)};
}
}
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 182e83eeea944..c59a5f543c606 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -43,7 +43,7 @@ using common::LanguageFeature;
using common::NumericOperator;
using common::TypeCategory;
-static inline std::string ToUpperCase(const std::string &str) {
+static inline std::string ToUpperCase(std::string_view str) {
return parser::ToUpperCaseLetters(str);
}
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 3659ead0a568d..0f6117b26a614 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -59,7 +59,7 @@ llvm::raw_ostream &PutAttrs(llvm::raw_ostream &, Attrs,
static llvm::raw_ostream &PutAttr(llvm::raw_ostream &, Attr);
static llvm::raw_ostream &PutType(llvm::raw_ostream &, const DeclTypeSpec &);
-static llvm::raw_ostream &PutLower(llvm::raw_ostream &, const std::string &);
+static llvm::raw_ostream &PutLower(llvm::raw_ostream &, std::string_view);
static std::error_code WriteFile(
const std::string &, const std::string &, bool = true);
static bool FileContentsMatch(
@@ -797,7 +797,7 @@ llvm::raw_ostream &PutType(llvm::raw_ostream &os, const DeclTypeSpec &type) {
return PutLower(os, type.AsFortran());
}
-llvm::raw_ostream &PutLower(llvm::raw_ostream &os, const std::string &str) {
+llvm::raw_ostream &PutLower(llvm::raw_ostream &os, std::string_view str) {
for (char c : str) {
os << parser::ToLowerCaseLetter(c);
}
diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index 4fe6ee4bd0076..67acf24cd254d 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -671,20 +671,20 @@ bool GenericKind::IsOperator() const {
std::string GenericKind::ToString() const {
return common::visit(
common::visitors {
- [](const OtherKind &x) { return EnumToString(x); },
+ [](const OtherKind &x) { return std::string{EnumToString(x)}; },
[](const DefinedIo &x) { return AsFortran(x).ToString(); },
#if !__clang__ && __GNUC__ == 7 && __GNUC_MINOR__ == 2
[](const common::NumericOperator &x) {
- return common::EnumToString(x);
+ return std::string{common::EnumToString(x)};
},
[](const common::LogicalOperator &x) {
- return common::EnumToString(x);
+ return std::string{common::EnumToString(x)};
},
[](const common::RelationalOperator &x) {
- return common::EnumToString(x);
+ return std::string{common::EnumToString(x)};
},
#else
- [](const auto &x) { return common::EnumToString(x); },
+ [](const auto &x) { return std::string{common::EnumToString(x)}; },
#endif
},
u);
More information about the flang-commits
mailing list