[flang] Add Attrs class to represent set of Attr
authorTim Keith <tkeith@nvidia.com>
Wed, 14 Feb 2018 23:07:59 +0000 (15:07 -0800)
committerTim Keith <tkeith@nvidia.com>
Wed, 14 Feb 2018 23:07:59 +0000 (15:07 -0800)
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
flang/lib/semantics/attr.h

index b75f9ab..ef97ba6 100644 (file)
@@ -1,56 +1,83 @@
+#include "../parser/idioms.h"
 #include "attr.h"
-
-#include <sstream>
-#include <string>
+#include <stddef.h>
 
 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<size_t>(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<Attr> 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
index 162e34c..c213455 100644 (file)
@@ -1,9 +1,8 @@
 #ifndef FORTRAN_ATTR_H_
 #define FORTRAN_ATTR_H_
 
-#include "../parser/idioms.h"
+#include <cinttypes>
 #include <iostream>
-#include <set>
 #include <string>
 
 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<Attr>;
+// Set of attributes
+class Attrs {
+public:
+  Attrs() : bits_{0} {}
+  Attrs(std::initializer_list<Attr> 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