[flang] Resolve build issues with older compilers.
authorpeter klausler <pklausler@nvidia.com>
Mon, 9 Jul 2018 23:23:12 +0000 (16:23 -0700)
committerpeter klausler <pklausler@nvidia.com>
Mon, 9 Jul 2018 23:26:01 +0000 (16:26 -0700)
Original-commit: flang-compiler/f18@d8723284d3750e05fbf6290d99faecd5cd8a774e
Reviewed-on: https://github.com/flang-compiler/f18/pull/117
Tree-same-pre-rewrite: false

flang/lib/common/idioms.h
flang/lib/common/indirection.h
flang/lib/evaluate/common.h
flang/lib/evaluate/expression.cc
flang/lib/evaluate/expression.h
flang/lib/evaluate/variable.cc
flang/lib/evaluate/variable.h

index 3004c58..39e3c5d 100644 (file)
@@ -25,8 +25,8 @@
 #if __cplusplus < 201703L
 #error this is a C++17 program
 #endif
-#if !defined(__clang__) && defined __GNUC__ && __GNUC__ < 7
-#error g++ >= 7.3 is required
+#if !__clang__ && defined __GNUC__ && __GNUC__ < 7
+#error g++ >= 7.2 is required
 #endif
 
 #include <list>
index 1778c98..b496ff6 100644 (file)
 // Intended to be as invisible as a reference, wherever possible.
 
 #include "../common/idioms.h"
+#include <type_traits>
 #include <utility>
 
 namespace Fortran::common {
 
-template<typename A> class Indirection {
+// The default case does not support (deep) copy construction and assignment.
+template<typename A, bool COPY = false> class Indirection {
+public:
+  using element_type = A;
+  Indirection() = delete;
+  Indirection(A *&&p) : p_{p} {
+    CHECK(p_ && "assigning null pointer to Indirection");
+    p = nullptr;
+  }
+  Indirection(A &&x) : p_{new A(std::move(x))} {}
+  Indirection(Indirection &&that) : p_{that.p_} {
+    CHECK(p_ && "move construction of Indirection from null Indirection");
+    that.p_ = nullptr;
+  }
+  ~Indirection() {
+    delete p_;
+    p_ = nullptr;
+  }
+  Indirection &operator=(Indirection &&that) {
+    CHECK(that.p_ && "move assignment of null Indirection to Indirection");
+    auto tmp = p_;
+    p_ = that.p_;
+    that.p_ = tmp;
+    return *this;
+  }
+  A &operator*() { return *p_; }
+  const A &operator*() const { return *p_; }
+  A *operator->() { return p_; }
+  const A *operator->() const { return p_; }
+
+  template<typename... ARGS> static Indirection Make(ARGS &&... args) {
+    return {new A(std::forward<ARGS>(args)...)};
+  }
+
+private:
+  A *p_{nullptr};
+};
+
+// Variant with copy construction and assignment
+template<typename A> class Indirection<A, true> {
 public:
   using element_type = A;
   Indirection() = delete;
index f6779ec..2f288d4 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "../common/enum-set.h"
 #include "../common/idioms.h"
+#include "../common/indirection.h"
 #include <cinttypes>
 
 namespace Fortran::evaluate {
@@ -120,5 +121,8 @@ using HostUnsignedInt =
   t &operator=(t &&) = default; \
   std::ostream &Dump(std::ostream &) const;
 
+// Force availability of copy construction and assignment
+template<typename A> using CopyableIndirection = common::Indirection<A, true>;
+
 }  // namespace Fortran::evaluate
 #endif  // FORTRAN_EVALUATE_COMMON_H_
index 5270d57..aeb6138 100644 (file)
@@ -69,7 +69,7 @@ template<int KIND>
 std::ostream &Expr<Category::Integer, KIND>::Dump(std::ostream &o) const {
   std::visit(
       common::visitors{[&](const Constant &n) { o << n.SignedDecimal(); },
-          [&](const common::Indirection<Designator> &d) { d->Dump(o); },
+          [&](const CopyableIndirection<Designator> &d) { d->Dump(o); },
           [&](const Parentheses &p) { p.Dump(o, "("); },
           [&](const Negate &n) { n.Dump(o, "(-"); },
           [&](const Add &a) { a.Dump(o, "+"); },
@@ -210,13 +210,19 @@ void Expr<Category::Integer, KIND>::Fold(FoldingContext &context) {
 
 template<int KIND>
 typename CharacterExpr<KIND>::LengthExpr CharacterExpr<KIND>::LEN() const {
-  return std::visit(common::visitors{[](const std::string &str) {
-                                       return LengthExpr{str.size()};
-                                     },
-                        [](const auto &concat) {
-                          return LengthExpr{LengthExpr::Add{
-                              concat.x->LEN(), concat.y->LEN()}};
-                        }},
+  // Written thus, instead of with common::visitors{}, to dodge a
+  // bug in g++ 7.2.0 that failed to direct the std::string case to its
+  // specific alternative.
+  return std::visit(
+      [](const auto &x) {
+        if constexpr (std::is_same_v<
+                          const typename CharacterExpr<KIND>::Constant &,
+                          decltype(x)>) {
+          return LengthExpr{x.size()};
+        } else {
+          return LengthExpr{LengthExpr::Add{x.x->LEN(), x.y->LEN()}};
+        }
+      },
       u);
 }
 
index 57f3e0e..0330eaa 100644 (file)
@@ -28,7 +28,6 @@
 #include "type.h"
 #include "variable.h"
 #include "../lib/common/idioms.h"
-#include "../lib/common/indirection.h"
 #include "../lib/parser/char-block.h"
 #include "../lib/parser/message.h"
 #include <ostream>
@@ -46,21 +45,21 @@ struct FoldingContext {
 template<typename A> struct Unary {
   CLASS_BOILERPLATE(Unary)
   Unary(const A &a) : x{a} {}
-  Unary(common::Indirection<A> &&a) : x{std::move(a)} {}
+  Unary(CopyableIndirection<A> &&a) : x{std::move(a)} {}
   Unary(A &&a) : x{std::move(a)} {}
   std::ostream &Dump(std::ostream &, const char *opr) const;
-  common::Indirection<A> x;
+  CopyableIndirection<A> x;
 };
 
 template<typename A, typename B = A> struct Binary {
   CLASS_BOILERPLATE(Binary)
   Binary(const A &a, const B &b) : x{a}, y{b} {}
-  Binary(common::Indirection<const A> &&a, common::Indirection<const B> &&b)
+  Binary(CopyableIndirection<const A> &&a, CopyableIndirection<const B> &&b)
     : x{std::move(a)}, y{std::move(b)} {}
   Binary(A &&a, B &&b) : x{std::move(a)}, y{std::move(b)} {}
   std::ostream &Dump(std::ostream &, const char *opr) const;
-  common::Indirection<A> x;
-  common::Indirection<B> y;
+  CopyableIndirection<A> x;
+  CopyableIndirection<B> y;
 };
 
 template<int KIND> struct Expr<Category::Integer, KIND> {
@@ -115,7 +114,7 @@ template<int KIND> struct Expr<Category::Integer, KIND> {
   void Fold(FoldingContext &);
 
   // TODO: function reference
-  std::variant<Constant, common::Indirection<Designator>,
+  std::variant<Constant, CopyableIndirection<Designator>,
       Convert<GenericIntegerExpr>, Convert<GenericRealExpr>, Parentheses,
       Negate, Add, Subtract, Multiply, Divide, Power>
       u;
index 6d67d4d..040c183 100644 (file)
@@ -69,7 +69,7 @@ std::ostream &Emit(
 }
 
 template<typename A>
-std::ostream &Emit(std::ostream &o, const common::Indirection<A> &p,
+std::ostream &Emit(std::ostream &o, const CopyableIndirection<A> &p,
     const char *kw = nullptr) {
   if (kw != nullptr) {
     o << kw;
index 5df4741..0302fd3 100644 (file)
@@ -24,7 +24,6 @@
 #include "common.h"
 #include "expression-forward.h"
 #include "../common/idioms.h"
-#include "../common/indirection.h"
 #include "../semantics/symbol.h"
 #include <optional>
 #include <ostream>
@@ -43,7 +42,7 @@ struct ActualFunctionArg;
 // Subscript and cosubscript expressions are of a kind that matches the
 // address size, at least at the top level.
 using SubscriptIntegerExpr =
-    common::Indirection<IntegerExpr<SubscriptInteger::kind>>;
+    CopyableIndirection<IntegerExpr<SubscriptInteger::kind>>;
 
 // R913 structure-component & C920: Defined to be a multi-part
 // data-ref whose last part has no subscripts (or image-selector, although
@@ -53,9 +52,9 @@ using SubscriptIntegerExpr =
 struct Component {
   CLASS_BOILERPLATE(Component)
   Component(const DataRef &b, const Symbol &c) : base{b}, sym{&c} {}
-  Component(common::Indirection<DataRef> &&b, const Symbol &c)
+  Component(CopyableIndirection<DataRef> &&b, const Symbol &c)
     : base{std::move(b)}, sym{&c} {}
-  common::Indirection<DataRef> base;
+  CopyableIndirection<DataRef> base;
   const Symbol *sym;
 };
 
@@ -109,7 +108,7 @@ struct CoarrayRef {
       cosubscript(std::move(css)) {}
   std::vector<const Symbol *> base;
   std::vector<SubscriptIntegerExpr> subscript, cosubscript;
-  std::optional<common::Indirection<Variable>> stat, team;
+  std::optional<CopyableIndirection<Variable>> stat, team;
   bool teamIsTeamNumber{false};  // false: TEAM=, true: TEAM_NUMBER=
 };
 
@@ -173,7 +172,7 @@ struct ProcedureDesignator {
 };
 
 template<typename ARG> struct ProcedureRef {
-  using ArgumentType = common::Indirection<ARG>;
+  using ArgumentType = CopyableIndirection<ARG>;
   CLASS_BOILERPLATE(ProcedureRef)
   ProcedureRef(ProcedureDesignator &&p, std::vector<ArgumentType> &&a)
     : proc{std::move(p)}, argument(std::move(a)) {}
@@ -194,7 +193,7 @@ struct ActualFunctionArg {
   CLASS_BOILERPLATE(ActualFunctionArg)
   explicit ActualFunctionArg(GenericExpr &&x) : u{std::move(x)} {}
   explicit ActualFunctionArg(Variable &&x) : u{std::move(x)} {}
-  std::variant<common::Indirection<GenericExpr>, Variable> u;
+  std::variant<CopyableIndirection<GenericExpr>, Variable> u;
 };
 
 struct Label {  // TODO: this is a placeholder
@@ -208,7 +207,7 @@ struct ActualSubroutineArg {
   explicit ActualSubroutineArg(GenericExpr &&x) : u{std::move(x)} {}
   explicit ActualSubroutineArg(Variable &&x) : u{std::move(x)} {}
   explicit ActualSubroutineArg(const Label &l) : u{&l} {}
-  std::variant<common::Indirection<GenericExpr>, Variable, const Label *> u;
+  std::variant<CopyableIndirection<GenericExpr>, Variable, const Label *> u;
 };
 
 using SubroutineRef = ProcedureRef<ActualSubroutineArg>;