From 9f755666fbc4e3f4d4d9643eccf352a3704678c4 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Fri, 23 Mar 2018 14:31:14 -0700 Subject: [PATCH] [flang] Add ENUM_CLASS to define enum class with ToString function. This replaces DEFINE_NESTED_ENUM_CLASS in parse-tree.h but works similarly. "ENUM_CLASS(Foo, A, B, C)" defined enum class Foo with enumerators A, B, C. It also defines an overloading of EnumToString that converts enumerators to their string representation. Change unparse.cc to adapt to this change. Make use of ENUM_CLASS in attr.h and attr.cc. Original-commit: flang-compiler/f18@c45b8f172a2559e22d1aaf12257b4e2558df8c6f Reviewed-on: https://github.com/flang-compiler/f18/pull/31 --- flang/lib/parser/idioms.cc | 19 ++++++++++++++++ flang/lib/parser/idioms.h | 10 +++++++++ flang/lib/parser/parse-tree.h | 52 +++++++++++++++++-------------------------- flang/lib/parser/unparse.cc | 51 +++++++++++++++++------------------------- flang/lib/semantics/attr.cc | 36 ++---------------------------- flang/lib/semantics/attr.h | 38 ++++++------------------------- 6 files changed, 79 insertions(+), 127 deletions(-) diff --git a/flang/lib/parser/idioms.cc b/flang/lib/parser/idioms.cc index 4600ee1..af23879 100644 --- a/flang/lib/parser/idioms.cc +++ b/flang/lib/parser/idioms.cc @@ -15,5 +15,24 @@ namespace parser { fputc('\n', stderr); std::abort(); } + +// Convert the int index of an enumerator to a string. +// enumNames is a list of the names, separated by commas with optional spaces. +// This is intended for use from the expansion of ENUM_CLASS. +std::string EnumIndexToString(int index, const char *enumNames) { + const char *p{enumNames}; + for (; index > 0; --index, ++p) { + for (; *p && *p != ','; ++p) { + } + } + for (; *p == ' '; ++p) { + } + CHECK(*p != '\0'); + const char *q = p; + for (; *q && *q != ' ' && *q != ','; ++q) { + } + return std::string(p, q - p); +} + } // namespace parser } // namespace Fortran diff --git a/flang/lib/parser/idioms.h b/flang/lib/parser/idioms.h index 04fa18e..0048e6e 100644 --- a/flang/lib/parser/idioms.h +++ b/flang/lib/parser/idioms.h @@ -102,6 +102,16 @@ template struct BadType : std::false_type {}; } \ } \ template constexpr bool T { class_trait_ns_##T::trait_value() } + +// Define enum class NAME with the given enumerators, and also a +// static function EnumToString that maps enumerators to std::string. +std::string EnumIndexToString(int index, const char *names); +#define ENUM_CLASS(NAME, ...) \ + enum class NAME { __VA_ARGS__ }; \ + static inline std::string EnumToString(NAME e) \ + { return Fortran::parser::EnumIndexToString( \ + static_cast(e), #__VA_ARGS__); } + } // namespace parser } // namespace Fortran #endif // FORTRAN_PARSER_IDIOMS_H_ diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index 56cc071..41a704d 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -94,14 +94,6 @@ CLASS_TRAIT(TupleTrait); WRAPPER_CLASS_BOILERPLATE(classname, type); \ } -// Enumeration types in classes can be defined with this macro, -// which also captures the names of the enums for formatting. -// Invocations an be followed by declarators and must be followed by -// a semicolon. -#define DEFINE_NESTED_ENUM_CLASS(ENUMTYPE, ...) \ - static constexpr const char *ENUMTYPE##AsString{#__VA_ARGS__}; \ - enum class ENUMTYPE { __VA_ARGS__ } - namespace Fortran { namespace parser { @@ -517,8 +509,8 @@ WRAPPER_CLASS(DefinedOpName, Name); // R610 extended-intrinsic-op -> intrinsic-operator struct DefinedOperator { UNION_CLASS_BOILERPLATE(DefinedOperator); - DEFINE_NESTED_ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, - Subtract, Concat, LT, LE, EQ, NE, GE, GT, NOT, AND, OR, XOR, EQV, NEQV); + ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat, + LT, LE, EQ, NE, GE, GT, NOT, AND, OR, XOR, EQV, NEQV) std::variant u; }; @@ -530,10 +522,11 @@ using ObjectName = Name; // IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL struct ImportStmt { BOILERPLATE(ImportStmt); - DEFINE_NESTED_ENUM_CLASS(Kind, Default, Only, None, All) kind{Kind::Default}; + ENUM_CLASS(Kind, Default, Only, None, All) ImportStmt(Kind &&k) : kind{k} {} ImportStmt(std::list &&n) : names(std::move(n)) {} ImportStmt(Kind &&, std::list &&); + Kind kind{Kind::Default}; std::list names; }; @@ -802,7 +795,7 @@ struct ConstantValue { // R807 access-spec -> PUBLIC | PRIVATE struct AccessSpec { - DEFINE_NESTED_ENUM_CLASS(Kind, Public, Private); + ENUM_CLASS(Kind, Public, Private) WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind); }; @@ -846,7 +839,7 @@ struct TypeParamDecl { // integer-type-spec , type-param-attr-spec :: type-param-decl-list // R734 type-param-attr-spec -> KIND | LEN struct TypeParamDefStmt { - DEFINE_NESTED_ENUM_CLASS(KindOrLen, Kind, Len); // R734 + ENUM_CLASS(KindOrLen, Kind, Len) // R734 TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt); std::tuple> t; }; @@ -1226,7 +1219,7 @@ struct ArraySpec { // R826 intent-spec -> IN | OUT | INOUT struct IntentSpec { - DEFINE_NESTED_ENUM_CLASS(Intent, In, Out, InOut); + ENUM_CLASS(Intent, In, Out, InOut) WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent); }; @@ -1303,7 +1296,7 @@ WRAPPER_CLASS(AsynchronousStmt, std::list); // R833 bind-entity -> entity-name | / common-block-name / struct BindEntity { TUPLE_CLASS_BOILERPLATE(BindEntity); - DEFINE_NESTED_ENUM_CLASS(Kind, Object, Common); + ENUM_CLASS(Kind, Object, Common) std::tuple t; }; @@ -1430,7 +1423,7 @@ WRAPPER_CLASS(ProtectedStmt, std::list); // R858 proc-pointer-name -> name struct SavedEntity { TUPLE_CLASS_BOILERPLATE(SavedEntity); - DEFINE_NESTED_ENUM_CLASS(Kind, Object, ProcPointer, Common); + ENUM_CLASS(Kind, Object, ProcPointer, Common) std::tuple t; }; @@ -1464,7 +1457,7 @@ struct ImplicitSpec { // R866 implicit-name-spec -> EXTERNAL | TYPE struct ImplicitStmt { UNION_CLASS_BOILERPLATE(ImplicitStmt); - DEFINE_NESTED_ENUM_CLASS(ImplicitNoneNameSpec, External, Type); // R866 + ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866 std::variant, std::list> u; }; @@ -2353,7 +2346,7 @@ struct StopCode { // R1161 error-stop-stmt -> // ERROR STOP [stop-code] [, QUIET = scalar-logical-expr] struct StopStmt { - DEFINE_NESTED_ENUM_CLASS(Kind, Stop, ErrorStop); + ENUM_CLASS(Kind, Stop, ErrorStop) TUPLE_CLASS_BOILERPLATE(StopStmt); std::tuple, std::optional> t; }; @@ -2469,9 +2462,8 @@ WRAPPER_CLASS(ErrLabel, Label); struct ConnectSpec { UNION_CLASS_BOILERPLATE(ConnectSpec); struct CharExpr { - DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, - Delim, Encoding, Form, Pad, Position, Round, Sign, - Dispose /*extension*/); + ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim, + Encoding, Form, Pad, Position, Round, Sign, Dispose /*extension*/) TUPLE_CLASS_BOILERPLATE(CharExpr); std::tuple t; }; @@ -2526,8 +2518,7 @@ WRAPPER_CLASS(EorLabel, Label); struct IoControlSpec { UNION_CLASS_BOILERPLATE(IoControlSpec); struct CharExpr { - DEFINE_NESTED_ENUM_CLASS( - Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign); + ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign) TUPLE_CLASS_BOILERPLATE(CharExpr); std::tuple t; }; @@ -2680,20 +2671,19 @@ WRAPPER_CLASS(FlushStmt, std::list); struct InquireSpec { UNION_CLASS_BOILERPLATE(InquireSpec); struct CharVar { - DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, - Delim, Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, - Read, Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, - Write); + ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim, + Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read, + Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write) TUPLE_CLASS_BOILERPLATE(CharVar); std::tuple t; }; struct IntVar { - DEFINE_NESTED_ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size); + ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size) TUPLE_CLASS_BOILERPLATE(IntVar); std::tuple t; }; struct LogVar { - DEFINE_NESTED_ENUM_CLASS(Kind, Exist, Named, Opened, Pending); + ENUM_CLASS(Kind, Exist, Named, Opened, Pending) TUPLE_CLASS_BOILERPLATE(LogVar); std::tuple>> t; }; @@ -2866,7 +2856,7 @@ struct Only { // R1410 module-nature -> INTRINSIC | NON_INTRINSIC struct UseStmt { BOILERPLATE(UseStmt); - DEFINE_NESTED_ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic); // R1410 + ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410 template UseStmt(std::optional &&nat, Name &&n, std::list &&x) : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {} @@ -2979,7 +2969,7 @@ struct InterfaceBody { // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list struct ProcedureStmt { - DEFINE_NESTED_ENUM_CLASS(Kind, ModuleProcedure, Procedure); + ENUM_CLASS(Kind, ModuleProcedure, Procedure) TUPLE_CLASS_BOILERPLATE(ProcedureStmt); std::tuple> t; }; diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index eaee8cd..0d98419 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -82,7 +82,7 @@ public: case DefinedOperator::IntrinsicOperator::GT: Put('>'); break; default: Put('.'); - PutEnum(static_cast(x), DefinedOperator::IntrinsicOperatorAsString); + Word(DefinedOperator::EnumToString(x)); Put('.'); } return false; @@ -1994,22 +1994,22 @@ public: return false; } -#define WALK_NESTED_ENUM(ENUMTYPE) \ - bool Pre(const ENUMTYPE &x) { \ - PutEnum(static_cast(x), ENUMTYPE##AsString); \ +#define WALK_NESTED_ENUM(CLASS, ENUM) \ + bool Pre(const CLASS::ENUM &x) { \ + Word(CLASS::EnumToString(x)); \ return false; \ } - WALK_NESTED_ENUM(AccessSpec::Kind) // R807 - WALK_NESTED_ENUM(TypeParamDefStmt::KindOrLen) // R734 - WALK_NESTED_ENUM(IntentSpec::Intent) // R826 - WALK_NESTED_ENUM(ImplicitStmt::ImplicitNoneNameSpec) // R866 - WALK_NESTED_ENUM(ConnectSpec::CharExpr::Kind) // R1205 - WALK_NESTED_ENUM(IoControlSpec::CharExpr::Kind) - WALK_NESTED_ENUM(InquireSpec::CharVar::Kind) - WALK_NESTED_ENUM(InquireSpec::IntVar::Kind) - WALK_NESTED_ENUM(InquireSpec::LogVar::Kind) - WALK_NESTED_ENUM(ProcedureStmt::Kind) // R1506 - WALK_NESTED_ENUM(UseStmt::ModuleNature) // R1410 + WALK_NESTED_ENUM(AccessSpec, Kind) // R807 + WALK_NESTED_ENUM(TypeParamDefStmt, KindOrLen) // R734 + WALK_NESTED_ENUM(IntentSpec, Intent) // R826 + WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866 + WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205 + WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind) + WALK_NESTED_ENUM(InquireSpec::CharVar, Kind) + WALK_NESTED_ENUM(InquireSpec::IntVar, Kind) + WALK_NESTED_ENUM(InquireSpec::LogVar, Kind) + WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506 + WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410 #undef WALK_NESTED_ENUM void Done() const { CHECK(indent_ == 0); } @@ -2020,8 +2020,8 @@ private: void Put(const std::string &); void PutKeywordLetter(char); void PutQuoted(const std::string &); - void PutEnum(int, const char *); void Word(const char *); + void Word(const std::string &); void Indent() { indent_ += indentationAmount_; } void Outdent() { CHECK(indent_ >= indentationAmount_); @@ -2144,27 +2144,16 @@ void UnparseVisitor::PutQuoted(const std::string &str) { Put('"'); } -void UnparseVisitor::PutEnum(int n, const char *enumNames) { - const char *p{enumNames}; - for (; n > 0; --n, ++p) { - for (; *p && *p != ','; ++p) { - } - } - while (*p == ' ') { - ++p; - } - CHECK(*p != '\0'); - for (; *p && *p != ' ' && *p != ','; ++p) { - PutKeywordLetter(*p); - } -} - void UnparseVisitor::Word(const char *str) { for (; *str != '\0'; ++str) { PutKeywordLetter(*str); } } +void UnparseVisitor::Word(const std::string &str) { + Word(str.c_str()); +} + void Unparse(std::ostream &out, const Program &program, Encoding encoding, bool capitalizeKeywords) { UnparseVisitor visitor{out, 1, encoding, capitalizeKeywords}; diff --git a/flang/lib/semantics/attr.cc b/flang/lib/semantics/attr.cc index 23483206..b492c3f 100644 --- a/flang/lib/semantics/attr.cc +++ b/flang/lib/semantics/attr.cc @@ -7,38 +7,6 @@ namespace semantics { constexpr static size_t toInt(Attr attr) { return static_cast(attr); } -static const char *attrToString[] = { - [toInt(Attr::ABSTRACT)] = "ABSTRACT", - [toInt(Attr::ALLOCATABLE)] = "ALLOCATABLE", - [toInt(Attr::ASYNCHRONOUS)] = "ASYNCHRONOUS", - [toInt(Attr::BIND_C)] = "BIND_C", - [toInt(Attr::CONTIGUOUS)] = "CONTIGUOUS", - [toInt(Attr::DEFERRED)] = "DEFERRED", - [toInt(Attr::ELEMENTAL)] = "ELEMENTAL", - [toInt(Attr::EXTERNAL)] = "EXTERNAL", - [toInt(Attr::IMPURE)] = "IMPURE", - [toInt(Attr::INTENT_IN)] = "INTENT_IN", - [toInt(Attr::INTENT_OUT)] = "INTENT_OUT", - [toInt(Attr::INTRINSIC)] = "INTRINSIC", - [toInt(Attr::MODULE)] = "MODULE", - [toInt(Attr::NON_OVERRIDABLE)] = "NON_OVERRIDABLE", - [toInt(Attr::NON_RECURSIVE)] = "NON_RECURSIVE", - [toInt(Attr::NOPASS)] = "NOPASS", - [toInt(Attr::OPTIONAL)] = "OPTIONAL", - [toInt(Attr::PARAMETER)] = "PARAMETER", - [toInt(Attr::PASS)] = "PASS", - [toInt(Attr::POINTER)] = "POINTER", - [toInt(Attr::PRIVATE)] = "PRIVATE", - [toInt(Attr::PROTECTED)] = "PROTECTED", - [toInt(Attr::PUBLIC)] = "PUBLIC", - [toInt(Attr::PURE)] = "PURE", - [toInt(Attr::RECURSIVE)] = "RECURSIVE", - [toInt(Attr::SAVE)] = "SAVE", - [toInt(Attr::TARGET)] = "TARGET", - [toInt(Attr::VALUE)] = "VALUE", - [toInt(Attr::VOLATILE)] = "VOLATILE", -}; - const Attrs Attrs::EMPTY; Attrs::Attrs(std::initializer_list attrs) { @@ -74,7 +42,7 @@ void Attrs::CheckValid(const Attrs &allowed) const { } std::ostream &operator<<(std::ostream &o, Attr attr) { - return o << attrToString[toInt(attr)]; + return o << EnumToString(attr); } std::ostream &operator<<(std::ostream &o, const Attrs &attrs) { @@ -84,7 +52,7 @@ std::ostream &operator<<(std::ostream &o, const Attrs &attrs) { if (n++) { o << ", "; } - o << attrToString[i]; + o << EnumToString(static_cast(i)); } } return o; diff --git a/flang/lib/semantics/attr.h b/flang/lib/semantics/attr.h index 80de37a..e6ff77e 100644 --- a/flang/lib/semantics/attr.h +++ b/flang/lib/semantics/attr.h @@ -1,6 +1,7 @@ #ifndef FORTRAN_ATTR_H_ #define FORTRAN_ATTR_H_ +#include "../parser/idioms.h" #include #include #include @@ -8,38 +9,13 @@ namespace Fortran { namespace semantics { + // All available attributes. -enum class Attr { - ABSTRACT, - ALLOCATABLE, - ASYNCHRONOUS, - BIND_C, - CONTIGUOUS, - DEFERRED, - ELEMENTAL, - EXTERNAL, - IMPURE, - INTENT_IN, - INTENT_OUT, - INTRINSIC, - MODULE, - NON_OVERRIDABLE, - NON_RECURSIVE, - NOPASS, - OPTIONAL, - PARAMETER, - PASS, - POINTER, - PRIVATE, - PROTECTED, - PUBLIC, - PURE, - RECURSIVE, - SAVE, - TARGET, - VALUE, - VOLATILE, -}; +ENUM_CLASS(Attr, ABSTRACT, ALLOCATABLE, ASYNCHRONOUS, BIND_C, CONTIGUOUS, + DEFERRED, ELEMENTAL, EXTERNAL, IMPURE, INTENT_IN, INTENT_OUT, INTRINSIC, + MODULE, NON_OVERRIDABLE, NON_RECURSIVE, NOPASS, OPTIONAL, PARAMETER, PASS, + POINTER, PRIVATE, PROTECTED, PUBLIC, PURE, RECURSIVE, SAVE, TARGET, VALUE, + VOLATILE) // Set of attributes class Attrs { -- 2.7.4