// confusing C++ reference forwarding semantics, e.g.
// template<typename A, NOT_LVALUE_REFERENCE(A)> void foo(A &&);
// Works on parameter packs as well.
-#define NOT_LVALUE_REFERENCE(X) bool = !std::is_lvalue_reference_v<X>
-#define NO_LVALUE_REFERENCE(X) bool = (... && !std::is_lvalue_reference_v<X>)
+#define NOT_LVALUE_REFERENCE(X) \
+ typename = std::enable_if_t<!std::is_lvalue_reference_v<X>, int>
+#define NO_LVALUE_REFERENCE(X) \
+ typename = std::enable_if_t<(... && !std::is_lvalue_reference_v<X>), int>
}
#endif // FORTRAN_COMMON_IDIOMS_H_
return std::nullopt;
}
+// Copy a value from one variant type to another. The types allowed in the
+// source variant must all be allowed in the destination variant type.
+template<typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) {
+ return std::visit([](const auto &x) -> TOV { return {x}; }, std::move(u));
+}
+
// Move a value from one variant type to another. The types allowed in the
// source variant must all be allowed in the destination variant type.
template<typename TOV, typename FROMV, NOT_LVALUE_REFERENCE(FROMV)>
#define EVALUATE_UNION_CLASS_BOILERPLATE(t) \
CLASS_BOILERPLATE(t) \
template<typename _A> explicit t(const _A &x) : u{x} {} \
- template<typename _A> \
- explicit t(std::enable_if_t<!std::is_reference_v<_A>, _A> &&x) \
- : u(std::move(x)) {} \
+ template<typename _A, NOT_LVALUE_REFERENCE(_A)> \
+ explicit t(_A &&x) : u(std::move(x)) {} \
bool operator==(const t &that) const { return u == that.u; }
// Forward definition of Expr<> so that it can be indirectly used in its own
using ScalarValue = SCALAR;
template<typename A> ConstantBase(const A &x) : values_{x} {}
- template<typename A>
- ConstantBase(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
- : values_{std::move(x)} {}
+ template<typename A, NOT_LVALUE_REFERENCE(A)>
+ ConstantBase(A &&x) : values_{std::move(x)} {}
ConstantBase(std::vector<ScalarValue> &&x, std::vector<std::int64_t> &&dims)
: values_(std::move(x)), shape_(std::move(dims)) {}
+ DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ConstantBase)
~ConstantBase();
int Rank() const { return static_cast<int>(shape_.size()); }
// Constructors and value-generating static functions
constexpr Integer() { Clear(); } // default constructor: zero
constexpr Integer(const Integer &) = default;
+ constexpr Integer(Integer &&) = default;
// C++'s integral types can all be converted to Integer
// with silent truncation.
- template<typename INT> constexpr Integer(INT n) {
- static_assert(std::is_integral_v<INT>);
+ template<typename INT,
+ typename = std::enable_if_t<std::is_integral_v<INT>, int>>
+ constexpr Integer(INT n) {
constexpr int nBits = CHAR_BIT * sizeof n;
if constexpr (nBits < partBits) {
if constexpr (std::is_unsigned_v<INT>) {
}
if (auto *constructor{UnwrapExpr<ArrayConstructor<ExtentType>>(arrayExpr)}) {
Shape result;
- for (const auto &value : constructor->values()) {
- if (const auto *expr{std::get_if<ExtentExpr>(&value.u)}) {
+ for (auto &value : constructor->values()) {
+ if (auto *expr{std::get_if<ExtentExpr>(&value.u)}) {
if (expr->Rank() == 0) {
result.emplace_back(std::move(*expr));
continue;
static_assert(IsSpecificIntrinsicType<Result> ||
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
EVALUATE_UNION_CLASS_BOILERPLATE(Designator)
- Designator(const DataRef &that) : u{common::MoveVariant<Variant>(that.u)} {}
+ Designator(const DataRef &that) : u{common::CopyVariant<Variant>(that.u)} {}
Designator(DataRef &&that)
: u{common::MoveVariant<Variant>(std::move(that.u))} {}
-// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
}
void Messages::AttachTo(Message &msg) {
- for (const Message &m : messages_) {
- msg.Attach(m);
+ for (Message &m : messages_) {
+ msg.Attach(std::move(m));
}
+ messages_.clear();
}
bool Messages::AnyFatalError() const {
attachmentIsContext_ = true;
}
Message &Attach(Message *);
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- Message &Attach(A &&... args) {
- return Attach(new Message{std::move(args)...}); // reference-counted
+ template<typename... A> Message &Attach(A &&... args) {
+ return Attach(new Message{std::forward<A>(args)...}); // reference-counted
}
bool SortBefore(const Message &that) const;
bool empty() const { return messages_.empty(); }
- template<typename... A, NO_LVALUE_REFERENCE(A)> Message &Say(A... args) {
- last_ = messages_.emplace_after(last_, std::move(args)...);
+ template<typename... A> Message &Say(A... args) {
+ last_ = messages_.emplace_after(last_, std::forward<A>(args)...);
return *last_;
}
return common::ScopedSet(at_, std::move(at));
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- Message *Say(CharBlock at, A &&... args) {
+ template<typename... A> Message *Say(CharBlock at, A &&... args) {
if (messages_ != nullptr) {
- return &messages_->Say(at, std::move(args)...);
+ return &messages_->Say(at, std::forward<A>(args)...);
} else {
return nullptr;
}
}
- template<typename... A, NO_LVALUE_REFERENCE(A)> Message *Say(A &&... args) {
- return Say(at_, std::move(args)...);
+ template<typename... A> Message *Say(A &&... args) {
+ return Say(at_, std::forward<A>(args)...);
}
private:
context_ = context_->attachment();
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- void Say(CharBlock range, A &&... args) {
+ template<typename... A> void Say(CharBlock range, A &&... args) {
if (deferMessages_) {
anyDeferredMessages_ = true;
} else {
- messages_.Say(range, std::move(args)...).SetContext(context_.get());
+ messages_.Say(range, std::forward<A>(args)...).SetContext(context_.get());
}
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- void Say(const MessageFixedText &text, A &&... args) {
- Say(p_, text, std::move(args)...);
+ template<typename... A> void Say(const MessageFixedText &text, A &&... args) {
+ Say(p_, text, std::forward<A>(args)...);
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
+ template<typename... A>
void Say(const MessageExpectedText &text, A &&... args) {
- Say(p_, text, std::move(args)...);
+ Say(p_, text, std::forward<A>(args)...);
}
void Nonstandard(LanguageFeature lf, const MessageFixedText &msg) {
return control && std::holds_alternative<LoopControl::Concurrent>(control->u);
}
-static Designator MakeArrayElementRef(Name &name, std::list<Expr> &subscripts) {
- ArrayElement arrayElement{name, std::list<SectionSubscript>{}};
+static Designator MakeArrayElementRef(
+ const Name &name, std::list<Expr> &subscripts) {
+ ArrayElement arrayElement{Name{name.source}, std::list<SectionSubscript>{}};
for (Expr &expr : subscripts) {
arrayElement.subscripts.push_back(SectionSubscript{
Scalar{Integer{common::Indirection{std::move(expr)}}}});
auto &funcExpr{std::get<Scalar<Expr>>(t).thing};
std::list<Expr> subscripts;
for (Name &arg : funcArgs) {
- subscripts.push_back(Expr{common::Indirection{Designator{arg}}});
+ subscripts.push_back(
+ Expr{common::Indirection{Designator{Name{arg.source}}}});
}
auto variable{
Variable{common::Indirection{MakeArrayElementRef(funcName, subscripts)}}};
TokenSequence TokenizePreprocessorDirective();
Provenance GetCurrentProvenance() const { return GetProvenance(at_); }
- template<typename... A, NO_LVALUE_REFERENCE(A)> Message &Say(A &&... a) {
- Message &m{messages_.Say(std::move(a)...)};
+ template<typename... A> Message &Say(A &&... a) {
+ Message &m{messages_.Say(std::forward<A>(a)...)};
std::optional<ProvenanceRange> range{m.GetProvenanceRange(cooked_)};
CHECK(!range.has_value() || cooked_.IsValid(*range));
return m;
MaskExpr GetMask(const parser::LogicalExpr &, bool defaultValue = true) const;
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- parser::Message *Say(A &&... args) {
- return messages_.Say(std::move(args)...);
+ template<typename... A> parser::Message *Say(A &&... args) {
+ return messages_.Say(std::forward<A>(args)...);
}
SemanticsContext &context_;
return GetFoldingContext().messages();
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- parser::Message *Say(A &&... args) {
- return GetContextualMessages().Say(std::move(args)...);
+ template<typename... A> parser::Message *Say(A &&... args) {
+ return GetContextualMessages().Say(std::forward<A>(args)...);
}
- template<typename T, typename... A, NO_LVALUE_REFERENCE(A)>
+ template<typename T, typename... A>
parser::Message *SayAt(const T &parsed, A &&... args) {
- return Say(parser::FindSourceLocation(parsed), std::move(args)...);
+ return Say(parser::FindSourceLocation(parsed), std::forward<A>(args)...);
}
int GetDefaultKind(common::TypeCategory);
}
}
- template<typename... A, NO_LVALUE_REFERENCE(A)>
- Message &Say(const parser::Name &name, A &&... args) {
- return messageHandler_.Say(name.source, std::move(args)...);
+ template<typename... A> Message &Say(A &&... args) {
+ return messageHandler_.Say(std::forward<A>(args)...);
}
- template<typename... A, NO_LVALUE_REFERENCE(A)> Message &Say(A &&... args) {
- return messageHandler_.Say(std::move(args)...);
+ template<typename... A>
+ Message &Say(
+ const parser::Name &name, MessageFixedText &&text, const A &... args) {
+ return messageHandler_.Say(name.source, std::move(text), args...);
}
private:
SayAlreadyDeclared(name, *symbol);
// replace the old symbol with a new one with correct details
EraseSymbol(*symbol);
- return MakeSymbol(name, attrs, details);
+ return MakeSymbol(name, attrs, std::move(details));
}
}
}
}
}
- details.add_dummyArg(MakeSymbol(dummyName, dummyDetails));
+ details.add_dummyArg(MakeSymbol(dummyName, std::move(dummyDetails)));
}
EraseSymbol(name); // added by PushSubprogramScope
EntityDetails resultDetails;
if (resultType) {
resultDetails.set_type(*resultType);
}
- details.set_result(MakeSymbol(name, resultDetails));
+ details.set_result(MakeSymbol(name, std::move(resultDetails)));
return true;
}
// add function result to function scope
EntityDetails funcResultDetails;
funcResultDetails.set_funcResult(true);
- funcInfo_.resultSymbol = &MakeSymbol(*funcResultName, funcResultDetails);
+ funcInfo_.resultSymbol =
+ &MakeSymbol(*funcResultName, std::move(funcResultDetails));
details.set_result(*funcInfo_.resultSymbol);
}
"Explicit SAVE of '%s' is redundant due to global SAVE statement"_err_en_US,
*saveInfo_.saveAll, "Global SAVE statement"_en_US);
} else if (auto msg{CheckSaveAttr(*symbol)}) {
- Say(name, *msg);
+ Say(name, std::move(*msg));
} else {
SetSaveAttr(*symbol);
}
std::holds_alternative<ProcBindingDetails>(details)) {
attrs.set(Attr::PRIVATE);
}
- Symbol &result{MakeSymbol(name, attrs, details)};
+ Symbol &result{MakeSymbol(name, attrs, std::move(details))};
if (result.has<TypeParamDetails>()) {
derivedType.symbol()->get<DerivedTypeDetails>().add_paramDecl(result);
}
bool RewriteMutator::Pre(parser::ExecutionPart &x) {
auto origFirst{x.v.begin()}; // insert each elem before origFirst
for (stmtFuncType &sf : stmtFuncsToConvert_) {
- auto &&stmt = sf.statement.value().ConvertToAssignment();
+ auto stmt{sf.statement.value().ConvertToAssignment()};
stmt.source = sf.source;
x.v.insert(origFirst,
- parser::ExecutionPartConstruct{parser::ExecutableConstruct{stmt}});
+ parser::ExecutionPartConstruct{
+ parser::ExecutableConstruct{std::move(stmt)}});
}
stmtFuncsToConvert_.clear();
return true;