From 6c168650b713a2bc1c98fc13e509807d232fba4f Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Wed, 14 Feb 2018 15:07:59 -0800 Subject: [PATCH] [flang] Add Attrs class to represent set of Attr Original-commit: flang-compiler/f18@8bb1f0eb9bee7c3de262eb82a9395127fd22db46 Reviewed-on: https://github.com/flang-compiler/f18/pull/8 Tree-same-pre-rewrite: false --- flang/lib/semantics/attr.cc | 107 +++++++++++++++++++++++++++----------------- flang/lib/semantics/attr.h | 27 ++++++++--- 2 files changed, 88 insertions(+), 46 deletions(-) diff --git a/flang/lib/semantics/attr.cc b/flang/lib/semantics/attr.cc index b75f9ab..ef97ba6 100644 --- a/flang/lib/semantics/attr.cc +++ b/flang/lib/semantics/attr.cc @@ -1,56 +1,83 @@ +#include "../parser/idioms.h" #include "attr.h" - -#include -#include +#include namespace Fortran { namespace semantics { -std::ostream &operator<<(std::ostream &o, Attr attr) { - switch (attr) { - case Attr::ABSTRACT: return o << "ABSTRACT"; - case Attr::ALLOCATABLE: return o << "ALLOCATABLE"; - case Attr::ASYNCHRONOUS: return o << "ASYNCHRONOUS"; - case Attr::BIND_C: return o << "BIND(C)"; - case Attr::CONTIGUOUS: return o << "CONTIGUOUS"; - case Attr::EXTERNAL: return o << "EXTERNAL"; - case Attr::INTENT_IN: return o << "INTENT_IN"; - case Attr::INTENT_OUT: return o << "INTENT_OUT"; - case Attr::INTRINSIC: return o << "INTRINSIC"; - case Attr::OPTIONAL: return o << "OPTIONAL"; - case Attr::PARAMETER: return o << "PARAMETER"; - case Attr::POINTER: return o << "POINTER"; - case Attr::PRIVATE: return o << "PRIVATE"; - case Attr::PROTECTED: return o << "PROTECTED"; - case Attr::PUBLIC: return o << "PUBLIC"; - case Attr::SAVE: return o << "SAVE"; - case Attr::TARGET: return o << "TARGET"; - case Attr::VALUE: return o << "VALUE"; - case Attr::VOLATILE: return o << "VOLATILE"; - default: CRASH_NO_CASE; +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::EXTERNAL)] = "EXTERNAL", + [toInt(Attr::INTENT_IN)] = "INTENT_IN", + [toInt(Attr::INTENT_OUT)] = "INTENT_OUT", + [toInt(Attr::INTRINSIC)] = "INTRINSIC", + [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::SAVE)] = "SAVE", + [toInt(Attr::TARGET)] = "TARGET", + [toInt(Attr::VALUE)] = "VALUE", + [toInt(Attr::VOLATILE)] = "VOLATILE", +}; + +Attrs::Attrs(std::initializer_list attrs) { + bits_ = 0; + for (auto attr : attrs) { + set(attr); } } -std::ostream &operator<<(std::ostream &o, const Attrs &attrs) { - int n = 0; - for (auto attr : attrs) { - if (n++) { - o << ", "; - } - o << attr; +Attrs &Attrs::set(Attr attr) { + bits_ |= 1u << toInt(attr); + return *this; +} +Attrs &Attrs::add(const Attrs &attrs) { + bits_ |= attrs.bits_; + return *this; +} + +bool Attrs::has(Attr attr) const { return (bits_ & (1u << toInt(attr))) != 0; } + +bool Attrs::hasAny(const Attrs &attrs) const { + return (bits_ & attrs.bits_) != 0; +} + +bool Attrs::hasAll(const Attrs &attrs) const { + return (bits_ & attrs.bits_) == attrs.bits_; +} + +void Attrs::checkValid(const Attrs &allowed) const { + if (!allowed.hasAll(*this)) { + parser::die("invalid attribute"); } - return o; } -void checkAttrs(std::string className, Attrs attrs, Attrs allowed) { - for (auto attr : attrs) { - if (allowed.find(attr) == allowed.end()) { - std::stringstream temp; - temp << attr; - parser::die("invalid attribute '%s' for class %s", temp.str().c_str(), - className.c_str()); +std::ostream &operator<<(std::ostream &o, Attr attr) { + return o << attrToString[toInt(attr)]; +} + +std::ostream &operator<<(std::ostream &o, const Attrs &attrs) { + int i = 0, n = 0; + for (std::uint64_t bits = attrs.bits_; bits != 0; bits >>= 1, ++i) { + if (bits & 1) { + if (n++) { + o << ", "; + } + o << attrToString[i]; } } + return o; } } // namespace semantics diff --git a/flang/lib/semantics/attr.h b/flang/lib/semantics/attr.h index 162e34c..c213455 100644 --- a/flang/lib/semantics/attr.h +++ b/flang/lib/semantics/attr.h @@ -1,9 +1,8 @@ #ifndef FORTRAN_ATTR_H_ #define FORTRAN_ATTR_H_ -#include "../parser/idioms.h" +#include #include -#include #include namespace Fortran { @@ -20,8 +19,10 @@ enum class Attr { INTENT_IN, INTENT_OUT, INTRINSIC, + NOPASS, OPTIONAL, PARAMETER, + PASS, POINTER, PRIVATE, PROTECTED, @@ -32,14 +33,28 @@ enum class Attr { VOLATILE, }; -using Attrs = std::set; +// Set of attributes +class Attrs { +public: + Attrs() : bits_{0} {} + Attrs(std::initializer_list attrs); + bool empty() const { return bits_ == 0; } + Attrs &set(Attr attr); + Attrs &add(const Attrs &attrs); + bool has(Attr attr) const; + bool hasAny(const Attrs &attrs) const; + bool hasAll(const Attrs &attrs) const; + // Internal error if any of these attributes are not in allowed. + void checkValid(const Attrs &allowed) const; + +private: + std::uint64_t bits_; + friend std::ostream &operator<<(std::ostream &, const Attrs &); +}; std::ostream &operator<<(std::ostream &o, Attr attr); std::ostream &operator<<(std::ostream &o, const Attrs &attrs); -// Report internal error if attrs is not a subset of allowed. -void checkAttrs(std::string className, Attrs attrs, Attrs allowed); - } // namespace semantics } // namespace Fortran -- 2.7.4