[flang] Fix flang-compiler/f18#312
authorpeter klausler <pklausler@nvidia.com>
Mon, 4 Mar 2019 19:23:50 +0000 (11:23 -0800)
committerpeter klausler <pklausler@nvidia.com>
Mon, 4 Mar 2019 19:23:50 +0000 (11:23 -0800)
Original-commit: flang-compiler/f18@625ffb4f1a09343725907fe51597e88e28a0ca91
Reviewed-on: https://github.com/flang-compiler/f18/pull/313
Tree-same-pre-rewrite: false

flang/documentation/C++style.md
flang/lib/common/indirection.h
flang/lib/evaluate/characteristics.cc
flang/lib/evaluate/characteristics.h
flang/lib/evaluate/expression.cc

index a95c8a5..7b30025 100644 (file)
@@ -196,8 +196,8 @@ not copyable, reassignable.
 counting, null by default, shallowly copyable, reassignable, and slow.
 * `OwningPointer<>`: A nullable pointer with ownership, better suited
 for use with forward-defined types than `std::unique_ptr<>` is.
-Null by default, not copyable, reassignable.
-Does not have means for allocating data, and inconveniently requires
+Null by default, optionally copyable, reassignable.
+Does not have direct means for allocating data, and inconveniently requires
 the definition of an external destructor.
 * `Indirection<>`: A non-nullable pointer with ownership and
 optional deep copy semantics; reassignable.
@@ -219,7 +219,7 @@ A feature matrix:
 | `&r`                 | no       | n/a          | no     | no           | shallowly         | yes                |
 | `unique_ptr<>`       | yes      | yes          | yes    | yes          | no                | no                 |
 | `shared_ptr<>`       | yes      | yes          | yes    | yes          | shallowly         | no                 |
-| `OwningPointer<>`    | yes      | yes          | yes    | yes          | no                | yes                |
+| `OwningPointer<>`    | yes      | yes          | yes    | yes          | optionally deeply | yes                |
 | `Indirection<>`      | no       | n/a          | yes    | yes          | optionally deeply | no                 |
 | `CountedReference<>` | yes      | yes          | yes    | yes          | shallowly         | no                 |
 
index c637128..620690c 100644 (file)
@@ -120,7 +120,8 @@ private:
 
 // A variant of Indirection suitable for use with forward-referenced types.
 // These are nullable pointers, not references.  Allocation is not available,
-// and a single externalized destructor must be defined.
+// and a single externalized destructor must be defined.  Copyable if an
+// external copy constructor and operator= are implemented.
 template<typename A> class OwningPointer {
 public:
   using element_type = A;
@@ -129,12 +130,20 @@ public:
   OwningPointer(OwningPointer &&that) : p_{that.release()} {}
   explicit OwningPointer(std::unique_ptr<A> &&that) : p_{that.release()} {}
   explicit OwningPointer(A *&&p) : p_{p} { p = nullptr; }
-  ~OwningPointer();
   OwningPointer &operator=(OwningPointer &&that) {
     reset(that.release());
     return *this;
   }
 
+  // Must be externally defined; see the macro below.
+  ~OwningPointer();
+
+  // Must be externally defined if copying is needed.
+  OwningPointer(const A &);
+  OwningPointer(const OwningPointer &);
+  OwningPointer &operator=(const A &);
+  OwningPointer &operator=(const OwningPointer &);
+
   A &operator*() { return *p_; }
   const A &operator*() const { return *p_; }
   A *operator->() { return p_; }
@@ -164,5 +173,40 @@ public:
 private:
   A *p_{nullptr};
 };
+
+// Mandatory instantiation and definition -- put somewhere, not in a namespace
+#define DEFINE_OWNING_POINTER_DESTRUCTOR(A) \
+  namespace Fortran::common { \
+  template class OwningPointer<A>; \
+  template<> OwningPointer<A>::~OwningPointer() { \
+    delete p_; \
+    p_ = nullptr; \
+  } \
+  }
+
+// Optional definitions
+#define DEFINE_OWNING_POINTER_COPY_CONSTRUCTORS(A) \
+  namespace Fortran::common { \
+  template<> \
+  OwningPointer<A>::OwningPointer(const A &that) : p_{new A(that)} {} \
+  template<> \
+  OwningPointer<A>::OwningPointer(const OwningPointer<A> &that) \
+    : p_{that.p_ ? new A(*that.p_) : nullptr} {} \
+  }
+#define DEFINE_OWNING_POINTER_COPY_ASSIGNMENTS(A) \
+  namespace Fortran::common { \
+  template<> OwningPointer<A> &OwningPointer<A>::operator=(const A &that) { \
+    delete p_; \
+    p_ = new A(that); \
+    return *this; \
+  } \
+  template<> \
+  OwningPointer<A> &OwningPointer<A>::operator=( \
+      const OwningPointer<A> &that) { \
+    delete p_; \
+    p_ = that.p_ ? new A(*that.p_) : nullptr; \
+    return *this; \
+  } \
+  }
 }
 #endif  // FORTRAN_COMMON_INDIRECTION_H_
index 4db93a2..c2dfa3b 100644 (file)
@@ -100,11 +100,7 @@ std::ostream &Procedure::Dump(std::ostream &o) const {
 }
 }
 
-namespace Fortran::common {
-template class OwningPointer<evaluate::characteristics::Procedure>;
-template<>
-OwningPointer<evaluate::characteristics::Procedure>::~OwningPointer() {
-  delete p_;
-  p_ = nullptr;
-}
-}
+// Define OwningPointer special member functions
+DEFINE_OWNING_POINTER_DESTRUCTOR(evaluate::characteristics::Procedure)
+DEFINE_OWNING_POINTER_COPY_CONSTRUCTORS(evaluate::characteristics::Procedure)
+DEFINE_OWNING_POINTER_COPY_ASSIGNMENTS(evaluate::characteristics::Procedure)
index 846617a..e445247 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef FORTRAN_EVALUATE_CHARACTERISTICS_H_
 #define FORTRAN_EVALUATE_CHARACTERISTICS_H_
 
+#include "common.h"
 #include "expression.h"
 #include "type.h"
 #include "../common/Fortran.h"
@@ -44,6 +45,7 @@ namespace Fortran::evaluate::characteristics {
 struct DummyDataObject {
   ENUM_CLASS(Attr, AssumedRank, Optional, Allocatable, Asynchronous, Contiguous,
       Value, Volatile, Polymorphic, Pointer, Target)
+  DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyDataObject)
   DynamicType type;
   std::vector<std::optional<Expr<SubscriptInteger>>> shape;
   std::vector<Expr<SubscriptInteger>> coshape;
@@ -56,6 +58,7 @@ struct DummyDataObject {
 // 15.3.2.3
 struct DummyProcedure {
   ENUM_CLASS(Attr, Pointer, Optional)
+  DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyProcedure)
   common::OwningPointer<Procedure> explicitProcedure;
   common::EnumSet<Attr, 32> attrs;
   bool operator==(const DummyProcedure &) const;
@@ -76,6 +79,7 @@ using DummyArgument =
 struct FunctionResult {
   ENUM_CLASS(
       Attr, Polymorphic, Allocatable, Pointer, Contiguous, ProcedurePointer)
+  DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(FunctionResult)
   DynamicType type;
   int rank{0};
   common::EnumSet<Attr, 32> attrs;
@@ -86,6 +90,8 @@ struct FunctionResult {
 // 15.3.1
 struct Procedure {
   ENUM_CLASS(Attr, Pure, Elemental, Bind_C)
+  Procedure() {}
+  DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure)
   std::optional<FunctionResult> functionResult;  // absent means subroutine
   std::vector<DummyArgument> dummyArguments;
   common::EnumSet<Attr, 32> attrs;
index ba46905..7f4cd1f 100644 (file)
@@ -321,10 +321,4 @@ FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor)
 // been embedded in the parse tree.  This destructor appears here, where
 // definitions for all the necessary types are available, to obviate a
 // need to include lib/evaluate/*.h headers in the parser proper.
-namespace Fortran::common {
-template class OwningPointer<evaluate::GenericExprWrapper>;
-template<> OwningPointer<evaluate::GenericExprWrapper>::~OwningPointer() {
-  delete p_;
-  p_ = nullptr;
-}
-}
+DEFINE_OWNING_POINTER_DESTRUCTOR(evaluate::GenericExprWrapper)