55 ENUM_CLASS(Attr, PassedObject, PercentVal, PercentRef);
63 explicit AssumedType(
const Symbol &);
64 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(AssumedType)
65 const Symbol &symbol()
const {
return symbol_; }
67 bool operator==(
const AssumedType &that)
const {
68 return &*symbol_ == &*that.symbol_;
70 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
81 class ConditionalArg {
84 std::optional<common::CopyableIndirection<Expr<SomeType>>>;
85 using ConditionalArgPartOrConsequent =
86 std::variant<common::CopyableIndirection<ConditionalArg>, Consequent>;
89 ConditionalArgPartOrConsequent &&tail);
90 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ConditionalArg)
94 const Consequent &consequent()
const {
return consequent_; }
95 Consequent &consequent() {
return consequent_; }
96 ConditionalArgPartOrConsequent &tail() {
return tail_; }
97 const ConditionalArgPartOrConsequent &tail()
const {
return tail_; }
102 template <
typename F,
typename G>
103 auto VisitTail(F onConditionalArg, G onConsequent)
const {
104 return common::visit(
106 [&](
const common::CopyableIndirection<ConditionalArg> &inner) {
107 return onConditionalArg(inner.value());
109 [&](
const Consequent &cons) {
return onConsequent(cons); },
114 template <
typename F,
typename G>
115 auto VisitTail(F onConditionalArg, G onConsequent) {
116 return common::visit(
118 [&](common::CopyableIndirection<ConditionalArg> &inner) {
119 return onConditionalArg(inner.value());
121 [&](Consequent &cons) {
return onConsequent(cons); },
129 template <
typename F>
void ForEachConsequent(F f)
const {
132 [&](
const ConditionalArg &inner) { inner.ForEachConsequent(f); },
133 [&](
const Consequent &cons) { f(cons); });
135 template <
typename F>
void ForEachConsequent(F f) {
137 VisitTail([&](ConditionalArg &inner) { inner.ForEachConsequent(f); },
138 [&](Consequent &cons) { f(cons); });
143 bool HasNilConsequent()
const;
145 bool operator==(
const ConditionalArg &)
const;
146 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
149 common::CopyableIndirection<Expr<SomeLogical>> condition_;
150 Consequent consequent_;
151 ConditionalArgPartOrConsequent tail_;
154 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(ActualArgument)
156 explicit ActualArgument(common::CopyableIndirection<
Expr<SomeType>> &&);
158 explicit ActualArgument(common::Label);
165 std::get_if<common::CopyableIndirection<Expr<SomeType>>>(&u_)}) {
171 const Expr<SomeType> *UnwrapExpr()
const {
173 std::get_if<common::CopyableIndirection<Expr<SomeType>>>(&u_)}) {
180 const Symbol *GetAssumedTypeDummy()
const {
181 if (
const AssumedType * aType{std::get_if<AssumedType>(&u_)}) {
182 return &aType->symbol();
188 common::Label GetLabel()
const {
return std::get<common::Label>(u_); }
190 std::optional<DynamicType> GetType()
const;
192 bool operator==(
const ActualArgument &)
const;
193 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
194 std::string AsFortran()
const;
196 std::optional<parser::CharBlock> keyword()
const {
return keyword_; }
197 ActualArgument &set_keyword(parser::CharBlock x) {
201 bool isAlternateReturn()
const {
202 return std::holds_alternative<common::Label>(u_);
204 bool isConditionalArg()
const {
205 return std::holds_alternative<ConditionalArg>(u_);
208 return std::get_if<ConditionalArg>(&u_);
211 return std::get_if<ConditionalArg>(&u_);
213 const Expr<SomeType> *GetConditionalArgExpr()
const {
214 const auto *condArg{GetConditionalArg()};
215 return condArg ? condArg->FirstNonNilConsequent() :
nullptr;
219 const Expr<SomeType> *GetArgExpr()
const {
220 if (
const auto *expr{UnwrapExpr()}) {
223 return GetConditionalArgExpr();
225 bool isPassedObject()
const {
return attrs_.test(Attr::PassedObject); }
226 ActualArgument &set_isPassedObject(
bool yes =
true) {
228 attrs_ = attrs_ + Attr::PassedObject;
230 attrs_ = attrs_ - Attr::PassedObject;
235 bool Matches(
const characteristics::DummyArgument &)
const;
236 common::Intent dummyIntent()
const {
return dummyIntent_; }
237 ActualArgument &set_dummyIntent(common::Intent intent) {
238 dummyIntent_ = intent;
241 std::optional<parser::CharBlock> sourceLocation()
const {
242 return sourceLocation_;
244 ActualArgument &set_sourceLocation(std::optional<parser::CharBlock> at) {
245 sourceLocation_ = at;
253 bool isPercentVal()
const {
return attrs_.test(Attr::PercentVal); };
254 ActualArgument &set_isPercentVal() {
255 attrs_ = attrs_ + Attr::PercentVal;
259 bool isPercentRef()
const {
return attrs_.test(Attr::PercentRef); };
260 ActualArgument &set_isPercentRef() {
261 attrs_ = attrs_ + Attr::PercentRef;
271 std::variant<common::CopyableIndirection<Expr<SomeType>>,
AssumedType,
274 std::optional<parser::CharBlock> keyword_;
276 common::Intent dummyIntent_{common::Intent::Default};
277 std::optional<parser::CharBlock> sourceLocation_;
298struct ProcedureDesignator {
299 EVALUATE_UNION_CLASS_BOILERPLATE(ProcedureDesignator)
301 explicit ProcedureDesignator(
const Symbol &n) : u{n} {}
302 explicit ProcedureDesignator(
Component &&);
306 const Symbol *GetSymbol()
const;
307 const SymbolRef *UnwrapSymbolRef()
const;
316 const Symbol *GetInterfaceSymbol()
const;
318 std::string GetName()
const;
319 std::optional<DynamicType> GetType()
const;
321 bool IsElemental()
const;
323 bool IsSimple()
const;
324 std::optional<Expr<SubscriptInteger>> LEN()
const;
325 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
328 common::CopyableIndirection<Component>>
336 CLASS_BOILERPLATE(ProcedureRef)
338 bool hasAlternateReturns =
false)
339 : proc_{std::move(p)}, arguments_{std::move(a)},
340 hasAlternateReturns_{hasAlternateReturns} {}
342 static void Deleter(ProcedureRef *);
346 ActualArguments &arguments() {
return arguments_; }
347 const ActualArguments &arguments()
const {
return arguments_; }
349 Chevrons &chevrons() {
return chevrons_; }
350 const Chevrons &chevrons()
const {
return chevrons_; }
351 void set_chevrons(Chevrons &&chevrons) { chevrons_ = std::move(chevrons); }
353 std::optional<Expr<SubscriptInteger>> LEN()
const;
355 static constexpr int Corank() {
return 0; }
356 bool IsElemental()
const {
return proc_.IsElemental(); }
357 bool hasAlternateReturns()
const {
return hasAlternateReturns_; }
359 bool hasNoInline()
const {
return noInline_; }
360 void setNoInline(
bool ni) { noInline_ = ni; }
361 bool hasAlwaysInline()
const {
return alwaysInline_; }
362 void setAlwaysInline(
bool ai) { alwaysInline_ = ai; }
363 bool hasInlineHint()
const {
return inlineHint_; }
364 void setInlineHint(
bool ih) { inlineHint_ = ih; }
367 if (
static_cast<std::size_t
>(n) < arguments_.size() && arguments_[n]) {
368 return arguments_[n]->UnwrapExpr();
374 if (
static_cast<std::size_t
>(n) < arguments_.size() && arguments_[n]) {
375 return arguments_[n]->UnwrapExpr();
381 bool operator==(
const ProcedureRef &)
const;
382 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
386 ActualArguments arguments_;
388 bool hasAlternateReturns_;
389 bool noInline_{
false};
390 bool alwaysInline_{
false};
391 bool inlineHint_{
false};
394template <
typename A>
class FunctionRef :
public ProcedureRef {
397 CLASS_BOILERPLATE(FunctionRef)
398 explicit FunctionRef(ProcedureRef &&pr) : ProcedureRef{std::move(pr)} {}
400 : ProcedureRef{std::move(p), std::move(a)} {}
402 std::optional<DynamicType> GetType()
const {
403 if constexpr (IsLengthlessIntrinsicType<A>) {
405 }
else if (
auto type{proc_.GetType()}) {
411 return type->DropNonConstantCharacterLength();