[flang] Use SomeExpr rather than GenericExprWrapper in checkers

Use GetExpr in checker classes to get analyzed expressions out of parse
tree nodes. Don't assume that they are always present. Change the
utility functions in tools.h to use SomeExpr rather than
GenericExprWrapper.

Original-commit: flang-compiler/f18@594e30d462
Reviewed-on: https://github.com/flang-compiler/f18/pull/422
Tree-same-pre-rewrite: false
This commit is contained in:
Tim Keith
2019-04-19 08:22:28 -07:00
parent a426477d37
commit 2107b223cb
4 changed files with 35 additions and 31 deletions

View File

@@ -19,8 +19,8 @@
namespace Fortran::semantics {
bool IsNumericExpr(const evaluate::GenericExprWrapper &expr) {
auto dynamicType{expr.v.GetType()};
bool IsNumericExpr(const SomeExpr &expr) {
auto dynamicType{expr.GetType()};
return dynamicType.has_value() &&
common::IsNumericTypeCategory(dynamicType->category);
}
@@ -31,17 +31,18 @@ void ArithmeticIfStmtChecker::Leave(
// The constraints and requirements here refer to the 2008 spec.
// R853 Check for a scalar-numeric-expr
// C849 that shall not be of type complex.
auto &expr{std::get<parser::Expr>(arithmeticIfStmt.t)};
if (expr.typedExpr->v.Rank() > 0) {
context_.Say(expr.source,
"ARITHMETIC IF expression must be a scalar expression"_err_en_US);
} else if (ExprHasTypeCategory(
*expr.typedExpr, common::TypeCategory::Complex)) {
context_.Say(expr.source,
"ARITHMETIC IF expression must not be a COMPLEX expression"_err_en_US);
} else if (!IsNumericExpr(*expr.typedExpr)) {
context_.Say(expr.source,
"ARITHMETIC IF expression must be a numeric expression"_err_en_US);
auto &parsedExpr{std::get<parser::Expr>(arithmeticIfStmt.t)};
if (const auto *expr{GetExpr(parsedExpr)}) {
if (expr->Rank() > 0) {
context_.Say(parsedExpr.source,
"ARITHMETIC IF expression must be a scalar expression"_err_en_US);
} else if (ExprHasTypeCategory(*expr, common::TypeCategory::Complex)) {
context_.Say(parsedExpr.source,
"ARITHMETIC IF expression must not be a COMPLEX expression"_err_en_US);
} else if (!IsNumericExpr(*expr)) {
context_.Say(parsedExpr.source,
"ARITHMETIC IF expression must be a numeric expression"_err_en_US);
}
}
// The labels have already been checked in resolve-labels.
// TODO: Really? Check that they are really branch target

View File

@@ -23,19 +23,18 @@
namespace Fortran::semantics {
void StopChecker::Enter(const parser::StopStmt &stmt) {
if (const auto &stopCode{std::get<std::optional<parser::StopCode>>(stmt.t)}) {
const parser::CharBlock &source{stopCode.value().v.thing.source};
const auto &expr{*(stopCode.value().v.thing.typedExpr)};
if (ExprHasTypeCategory(expr, common::TypeCategory::Integer)) {
const auto &stopCode{std::get<std::optional<parser::StopCode>>(stmt.t)};
if (const auto *expr{GetExpr(stopCode)}) {
const parser::CharBlock &source{parser::FindSourceLocation(stopCode)};
if (ExprHasTypeCategory(*expr, common::TypeCategory::Integer)) {
// C1171 default kind
if (!(ExprTypeKindIsDefault(expr, context_))) {
if (!ExprTypeKindIsDefault(*expr, context_)) {
context_.Say(
source, "INTEGER stop code must be of default kind"_err_en_US);
}
} else if (ExprHasTypeCategory(expr, common::TypeCategory::Character)) {
} else if (ExprHasTypeCategory(*expr, common::TypeCategory::Character)) {
// R1162 spells scalar-DEFAULT-char-expr
if (!(ExprTypeKindIsDefault(expr, context_))) {
if (!ExprTypeKindIsDefault(*expr, context_)) {
context_.Say(
source, "CHARACTER stop code must be of default kind"_err_en_US);
}

View File

@@ -277,15 +277,15 @@ const Symbol *FindExternallyVisibleObject(
}
}
bool ExprHasTypeCategory(const evaluate::GenericExprWrapper &expr,
const common::TypeCategory &type) {
auto dynamicType{expr.v.GetType()};
bool ExprHasTypeCategory(
const SomeExpr &expr, const common::TypeCategory &type) {
auto dynamicType{expr.GetType()};
return dynamicType.has_value() && dynamicType->category == type;
}
bool ExprTypeKindIsDefault(
const evaluate::GenericExprWrapper &expr, const SemanticsContext &context) {
auto dynamicType{expr.v.GetType()};
const SomeExpr &expr, const SemanticsContext &context) {
auto dynamicType{expr.GetType()};
return dynamicType.has_value() &&
dynamicType->category != common::TypeCategory::Derived &&
dynamicType->kind ==

View File

@@ -18,6 +18,7 @@
// Simple predicates and look-up functions that are best defined
// canonically for use in semantic checking.
#include "expression.h"
#include "semantics.h"
#include "../common/Fortran.h"
#include "../evaluate/expression.h"
@@ -95,13 +96,13 @@ const Symbol *FindExternallyVisibleObject(
expr.u);
}
bool ExprHasTypeCategory(
const evaluate::GenericExprWrapper &expr, const common::TypeCategory &type);
bool ExprTypeKindIsDefault(
const evaluate::GenericExprWrapper &expr, const SemanticsContext &context);
using SomeExpr = evaluate::Expr<evaluate::SomeType>;
bool ExprHasTypeCategory(
const SomeExpr &expr, const common::TypeCategory &type);
bool ExprTypeKindIsDefault(
const SomeExpr &expr, const SemanticsContext &context);
struct GetExprHelper {
const SomeExpr *Get(const parser::Expr::TypedExpr &x) {
return x ? &x->v : nullptr;
@@ -111,6 +112,9 @@ struct GetExprHelper {
template<typename T> const SomeExpr *Get(const common::Indirection<T> &x) {
return Get(x.value());
}
template<typename T> const SomeExpr *Get(const std::optional<T> &x) {
return x.has_value() ? Get(x.value()) : nullptr;
}
template<typename T> const SomeExpr *Get(const T &x) {
if constexpr (ConstraintTrait<T>) {
return Get(x.thing);