mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 12:19:23 +08:00
[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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 ==
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user