[flang] Address review comments

Original-commit: flang-compiler/f18@2393157d3f
Reviewed-on: https://github.com/flang-compiler/f18/pull/755
This commit is contained in:
peter klausler 2019-09-24 14:17:50 -07:00
parent 9fd72e9393
commit ccb91afba7
2 changed files with 37 additions and 46 deletions

View File

@ -28,8 +28,6 @@
// The client (Visitor) of Traverse<Visitor,Result> must define:
// - a member function "Result Default();"
// - a member function "Result Combine(Result &&, Result &&)"
// - a default "template<typename A> Result operator()(const A &x) const"
// handler that reflects back into Traverse<Visitor, Result>
// - overrides for "Result operator()"
//
// Boilerplate classes also appear below to ease construction of visitors.
@ -247,55 +245,39 @@ private:
Visitor &visitor_;
};
template<typename Visitor, typename Result> class TraverseBase {
public:
explicit TraverseBase(Visitor &v) : traverse_{v} {}
static Result Default() { return {}; }
template<typename A> Result operator()(const A &x) const {
return traverse_(x);
}
private:
Traverse<Visitor, Result> traverse_;
};
template<typename Visitor, typename Result = bool, bool isConjunction = true,
typename Base = TraverseBase<Visitor, Result>>
struct CombiningTraverse : public Base {
using Base::Base;
// For validity checks across an expression: if any operator() result is
// false, so is the overall result.
template<typename Visitor, typename Base = Traverse<Visitor, bool>>
struct AllTraverse : public Base {
AllTraverse(Visitor &v) : Base{v} {}
using Base::operator();
static Result Default() {
if constexpr (isConjunction && std::is_same_v<Result, bool>) {
return true;
} else {
return {};
}
}
static Result Combine(Result &&x, Result &&y) {
if (static_cast<bool>(x) == isConjunction) {
return std::move(y);
} else {
return std::move(x);
}
}
static bool Default() { return true; }
static bool Combine(bool x, bool y) { return x && y; }
};
// For validity checks across an expression: if any operator() is
// false, the result is false.
template<typename Visitor, typename Result = bool>
using AllTraverse = CombiningTraverse<Visitor, Result, true>;
// For searches over an expression: the first operator() result that
// is truthful is the final result. Works for Booleans, pointers,
// and std::optional<>.
template<typename Visitor, typename Result = bool>
using AnyTraverse = CombiningTraverse<Visitor, Result, false>;
template<typename Visitor, typename Set,
typename Base = TraverseBase<Visitor, Set>>
struct SetTraverse : public Base {
using Base::Base;
template<typename Visitor, typename Result = bool,
typename Base = Traverse<Visitor, Result>>
struct AnyTraverse : public Base {
AnyTraverse(Visitor &v) : Base{v} {}
using Base::operator();
static Result Default() { return {}; }
static Result Combine(Result &&x, Result &&y) {
if (x) {
return std::move(x);
} else {
return std::move(y);
}
}
};
template<typename Visitor, typename Set, typename Base = Traverse<Visitor, Set>>
struct SetTraverse : public Base {
SetTraverse(Visitor &v) : Base{v} {}
using Base::operator();
static Set Default() { return {}; }
static Set Combine(Set &&x, Set &&y) {
#if CLANG_LIBRARIES // no std::set::merge()
for (auto &value : y) {
@ -307,5 +289,6 @@ struct SetTraverse : public Base {
return std::move(x);
}
};
}
#endif

View File

@ -2210,8 +2210,16 @@ MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
}
}
}
if (const Symbol *symbol{proc.GetSymbol()}) {
if (const auto *details{symbol->detailsIf<semantics::SubprogramNameDetails>()}) {
if (const Symbol * symbol{proc.GetSymbol()}) {
if (const auto *details{
symbol->detailsIf<semantics::SubprogramNameDetails>()}) {
// If this symbol is still a SubprogramNameDetails, we must be
// checking a specification expression in a sibling module or internal
// procedure. Since recursion is disallowed in specification
// expressions, we should handle such references by processing the
// sibling procedure's specification part right now (recursively),
// but until we can do so, just complain about the forward reference.
// TODO: recursively process sibling's specification part.
if (details->kind() == semantics::SubprogramKind::Module) {
Say("The module function '%s' must have been previously defined "
"when referenced in a specification expression"_err_en_US,