[flang] Add Attrs class to represent set of Attr

Original-commit: flang-compiler/f18@8bb1f0eb9b
Reviewed-on: https://github.com/flang-compiler/f18/pull/8
Tree-same-pre-rewrite: false
This commit is contained in:
Tim Keith 2018-02-14 15:07:59 -08:00
parent b21afad445
commit 6c168650b7
2 changed files with 89 additions and 47 deletions

View file

@ -1,57 +1,84 @@
#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);
}
}
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");
}
}
std::ostream &operator<<(std::ostream &o, Attr attr) {
return o << attrToString[toInt(attr)];
}
std::ostream &operator<<(std::ostream &o, const Attrs &attrs) {
int n = 0;
for (auto attr : attrs) {
if (n++) {
o << ", ";
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];
}
o << attr;
}
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());
}
}
}
} // namespace semantics
} // namespace Fortran

View 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