Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Common/indirection.h ----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_COMMON_INDIRECTION_H_
10#define FORTRAN_COMMON_INDIRECTION_H_
11
12// Define a smart pointer class template that is rather like
13// non-nullable std::unique_ptr<>. Indirection<> is, like a C++ reference
14// type, restricted to be non-null when constructed or assigned.
15// Indirection<> optionally supports copy construction and copy assignment.
16//
17// To use Indirection<> with forward-referenced types, add
18// extern template class Fortran::common::Indirection<FORWARD_TYPE>;
19// outside any namespace in a header before use, and
20// template class Fortran::common::Indirection<FORWARD_TYPE>;
21// in one C++ source file later where a definition of the type is visible.
22
23#include "idioms.h"
24#include <memory>
25#include <type_traits>
26#include <utility>
27
28namespace Fortran::common {
29
30// The default case does not support (deep) copy construction or assignment.
31template <typename A, bool COPY = false> class Indirection {
32public:
33 using element_type = A;
34 Indirection() = delete;
35 Indirection(A *&&p) : p_{p} {
36 CHECK(p_ && "assigning null pointer to Indirection");
37 p = nullptr;
38 }
39 Indirection(A &&x) : p_{new A(std::move(x))} {}
40 Indirection(Indirection &&that) : p_{that.p_} {
41 CHECK(p_ && "move construction of Indirection from null Indirection");
42 that.p_ = nullptr;
43 }
44 ~Indirection() {
45 delete p_;
46 p_ = nullptr;
47 }
48 Indirection &operator=(Indirection &&that) {
49 CHECK(that.p_ && "move assignment of null Indirection to Indirection");
50 auto tmp{p_};
51 p_ = that.p_;
52 that.p_ = tmp;
53 return *this;
54 }
55
56 A &value() { return *p_; }
57 const A &value() const { return *p_; }
58
59 bool operator==(const A &that) const { return *p_ == that; }
60 bool operator==(const Indirection &that) const { return *p_ == *that.p_; }
61
62 template <typename... ARGS>
63 static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&...args) {
64 return {new A(std::move(args)...)};
65 }
66
67private:
68 A *p_{nullptr};
69};
70
71// Variant with copy construction and assignment
72template <typename A> class Indirection<A, true> {
73public:
74 using element_type = A;
75
76 Indirection() = delete;
77 Indirection(A *&&p) : p_{p} {
78 CHECK(p_ && "assigning null pointer to Indirection");
79 p = nullptr;
80 }
81 Indirection(const A &x) : p_{new A(x)} {}
82 Indirection(A &&x) : p_{new A(std::move(x))} {}
83 Indirection(const Indirection &that) {
84 CHECK(that.p_ && "copy construction of Indirection from null Indirection");
85 p_ = new A(*that.p_);
86 }
87 Indirection(Indirection &&that) : p_{that.p_} {
88 CHECK(p_ && "move construction of Indirection from null Indirection");
89 that.p_ = nullptr;
90 }
91 ~Indirection() {
92 delete p_;
93 p_ = nullptr;
94 }
95 Indirection &operator=(const Indirection &that) {
96 CHECK(that.p_ && "copy assignment of Indirection from null Indirection");
97 *p_ = *that.p_;
98 return *this;
99 }
100 Indirection &operator=(Indirection &&that) {
101 CHECK(that.p_ && "move assignment of null Indirection to Indirection");
102 auto tmp{p_};
103 p_ = that.p_;
104 that.p_ = tmp;
105 return *this;
106 }
107
108 A &value() { return *p_; }
109 const A &value() const { return *p_; }
110
111 bool operator==(const A &that) const { return *p_ == that; }
112 bool operator==(const Indirection &that) const { return *p_ == *that.p_; }
113
114 template <typename... ARGS>
115 static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&...args) {
116 return {new A(std::move(args)...)};
117 }
118
119private:
120 A *p_{nullptr};
121};
122
123template <typename A> using CopyableIndirection = Indirection<A, true>;
124
125// A variation of std::unique_ptr<> with a reified deletion routine.
126// Used to avoid dependence cycles between shared libraries.
127template <typename A> class ForwardOwningPointer {
128public:
129 ForwardOwningPointer() {}
130 ForwardOwningPointer(A *p, void (*del)(A *)) : p_{p}, deleter_{del} {}
131 ForwardOwningPointer(ForwardOwningPointer &&that)
132 : p_{that.p_}, deleter_{that.deleter_} {
133 that.p_ = nullptr;
134 }
135 ForwardOwningPointer &operator=(ForwardOwningPointer &&that) {
136 p_ = that.p_;
137 that.p_ = nullptr;
138 deleter_ = that.deleter_;
139 return *this;
140 }
141 ~ForwardOwningPointer() {
142 if (p_) {
143 deleter_(p_);
144 }
145 }
146
147 A &operator*() const { return *p_; }
148 A *operator->() const { return p_; }
149 operator bool() const { return p_ != nullptr; }
150 A *get() { return p_; }
151 auto get() const { return reinterpret_cast<std::add_const_t<A> *>(p_); }
152 A *release() {
153 A *result{p_};
154 p_ = nullptr;
155 return result;
156 }
157
158 void Reset(A *p = nullptr) {
159 if (p_) {
160 deleter_(p_);
161 }
162 p_ = p;
163 }
164 void Reset(A *p, void (*del)(A *)) {
165 Reset(p);
166 deleter_ = del;
167 }
168
169private:
170 A *p_{nullptr};
171 void (*deleter_)(A *){nullptr};
172};
173} // namespace Fortran::common
174#endif // FORTRAN_COMMON_INDIRECTION_H_
175

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Common/indirection.h