[flang] Add message.{h,cc}.
authorpeter klausler <pklausler@nvidia.com>
Tue, 30 Jan 2018 19:53:49 +0000 (11:53 -0800)
committerpeter klausler <pklausler@nvidia.com>
Tue, 30 Jan 2018 19:53:49 +0000 (11:53 -0800)
Original-commit: flang-compiler/f18@9c21346414a4e13f1bef8b40607880fbcb9bb7f6

flang/message.cc [new file with mode: 0644]
flang/message.h [new file with mode: 0644]

diff --git a/flang/message.cc b/flang/message.cc
new file mode 100644 (file)
index 0000000..55cdbf4
--- /dev/null
@@ -0,0 +1,24 @@
+#include "message.h"
+
+namespace Fortran {
+
+std::ostream &operator<<(std::ostream &o, const Message &msg) {
+  if (msg.context()) {
+    o << *msg.context();
+  }
+  o << "at line " << msg.position().lineNumber();
+  int column = msg.position().column();
+  if (column > 0) {
+    o << "(column " << column << ")";
+  }
+  o << ": " << msg.message() << '\n';
+  return o;
+}
+
+std::ostream &operator<<(std::ostream &o, const Messages &ms) {
+  for (const auto &msg : ms) {
+    o << msg;
+  }
+  return o;
+}
+}  // namespace Fortran
diff --git a/flang/message.h b/flang/message.h
new file mode 100644 (file)
index 0000000..c98ea9b
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef FORTRAN_MESSAGE_H_
+#define FORTRAN_MESSAGE_H_
+
+// Defines a representation for sequences of compiler messages.
+// Supports nested contextualization.
+
+#include "idioms.h"
+#include "position.h"
+#include <forward_list>
+#include <memory>
+#include <optional>
+#include <ostream>
+#include <string>
+
+namespace Fortran {
+
+class Message;
+using MessageContext = std::shared_ptr<Message>;
+
+class Message {
+ public:
+  Message(Position pos, const std::string &msg, MessageContext ctx = nullptr)
+    : position_{pos}, message_{msg}, context_{ctx} {}
+  Message(Position pos, std::string &&msg, MessageContext ctx = nullptr)
+    : position_{pos}, message_{std::move(msg)}, context_{ctx} {}
+  Message(Position pos, const char *msg, MessageContext ctx = nullptr)
+    : position_{pos}, message_{msg}, context_{ctx} {}
+  Message(Position pos, char ch, MessageContext ctx = nullptr)
+    : position_{pos}, message_{"expected '"s + ch + '\''},
+      context_{ctx} {}
+
+  Message() {}
+  Message(const Message &) = default;
+  Message(Message &&) = default;
+  Message &operator=(const Message &that) = default;
+  Message &operator=(Message &&that) = default;
+
+  Position position() const { return position_; }
+  std::string message() const { return message_; }
+  MessageContext context() const { return context_; }
+
+  bool operator<(const Message &that) const {
+    return position_ < that.position_;
+  }
+
+ private:
+  Position position_;
+  std::string message_;
+  MessageContext context_;
+};
+
+class Messages {
+  using list_type = std::forward_list<Message>;
+ public:
+  using iterator = list_type::iterator;
+  using const_iterator = list_type::const_iterator;
+
+  Messages() {}
+  Messages(Messages &&that)
+    : messages_{std::move(that.messages_)}, last_{that.last_} {}
+  Messages &operator=(Messages &&that) {
+    swap(that);
+    return *this;
+  }
+
+  void swap(Messages &that) {
+    messages_.swap(that.messages_);
+    std::swap(last_, that.last_);
+  }
+
+  iterator begin() { return messages_.begin(); }
+  iterator end() { return messages_.end(); }
+  const_iterator begin() const { return messages_.cbegin(); }
+  const_iterator end() const { return messages_.cend(); }
+  const_iterator cbegin() const { return messages_.cbegin(); }
+  const_iterator cend() const { return messages_.cend(); }
+
+  void Add(Message &&m) {
+    if (messages_.empty()) {
+      messages_.emplace_front(std::move(m));
+      last_ = messages_.begin();
+    } else {
+      last_ = messages_.emplace_after(last_, std::move(m));
+    }
+  }
+
+  void Annex(Messages *that) {
+    if (!that->messages_.empty()) {
+      if (messages_.empty()) {
+        messages_ = std::move(that->messages_);
+      } else {
+        messages_.splice_after(last_, that->messages_);
+      }
+      last_ = that->last_;
+    }
+  }
+
+ private:
+  list_type messages_;
+  iterator last_;  // valid iff messages_ nonempty
+};
+
+std::ostream &operator<<(std::ostream &, const Message &);
+std::ostream &operator<<(std::ostream &, const Messages &);
+}  // namespace Fortran
+#endif  // FORTRAN_MESSAGE_H_