1 //===-- include/flang/Evaluate/check-expression.h ---------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Static expression checking 10 11 #ifndef FORTRAN_EVALUATE_CHECK_EXPRESSION_H_ 12 #define FORTRAN_EVALUATE_CHECK_EXPRESSION_H_ 13 14 #include "expression.h" 15 #include "intrinsics.h" 16 #include "type.h" 17 #include <optional> 18 19 namespace Fortran::parser { 20 class ContextualMessages; 21 } 22 namespace Fortran::semantics { 23 class Scope; 24 } 25 26 namespace Fortran::evaluate { 27 28 // Predicate: true when an expression is a constant expression (in the 29 // strict sense of the Fortran standard); it may not (yet) be a hard 30 // constant value. 31 template <typename A> bool IsConstantExpr(const A &); 32 extern template bool IsConstantExpr(const Expr<SomeType> &); 33 extern template bool IsConstantExpr(const Expr<SomeInteger> &); 34 extern template bool IsConstantExpr(const Expr<SubscriptInteger> &); 35 extern template bool IsConstantExpr(const StructureConstructor &); 36 37 // Predicate: true when an expression is a constant expression (in the 38 // strict sense of the Fortran standard) or a dummy argument with 39 // INTENT(IN) and no VALUE. This is useful for representing explicit 40 // shapes of other dummy arguments. 41 template <typename A> bool IsScopeInvariantExpr(const A &); 42 extern template bool IsScopeInvariantExpr(const Expr<SomeType> &); 43 extern template bool IsScopeInvariantExpr(const Expr<SomeInteger> &); 44 extern template bool IsScopeInvariantExpr(const Expr<SubscriptInteger> &); 45 46 // Predicate: true when an expression actually is a typed Constant<T>, 47 // perhaps with parentheses and wrapping around it. False for all typeless 48 // expressions, including BOZ literals. 49 template <typename A> bool IsActuallyConstant(const A &); 50 extern template bool IsActuallyConstant(const Expr<SomeType> &); 51 extern template bool IsActuallyConstant(const Expr<SomeInteger> &); 52 extern template bool IsActuallyConstant(const Expr<SubscriptInteger> &); 53 extern template bool IsActuallyConstant( 54 const std::optional<Expr<SubscriptInteger>> &); 55 56 // Checks whether an expression is an object designator with 57 // constant addressing and no vector-valued subscript. 58 // If a non-null ContextualMessages pointer is passed, an error message 59 // will be generated if and only if the result of the function is false. 60 bool IsInitialDataTarget( 61 const Expr<SomeType> &, parser::ContextualMessages * = nullptr); 62 63 bool IsInitialProcedureTarget(const Symbol &); 64 bool IsInitialProcedureTarget(const ProcedureDesignator &); 65 bool IsInitialProcedureTarget(const Expr<SomeType> &); 66 67 // Validate the value of a named constant, the static initial 68 // value of a non-pointer non-allocatable non-dummy variable, or the 69 // default initializer of a component of a derived type (or instantiation 70 // of a derived type). Converts type and expands scalars as necessary. 71 std::optional<Expr<SomeType>> NonPointerInitializationExpr(const Symbol &, 72 Expr<SomeType> &&, FoldingContext &, 73 const semantics::Scope *instantiation = nullptr); 74 75 // Check whether an expression is a specification expression 76 // (10.1.11(2), C1010). Constant expressions are always valid 77 // specification expressions. 78 79 template <typename A> 80 void CheckSpecificationExpr(const A &, const semantics::Scope &, 81 FoldingContext &, bool forElementalFunctionResult); 82 extern template void CheckSpecificationExpr(const Expr<SomeType> &x, 83 const semantics::Scope &, FoldingContext &, 84 bool forElementalFunctionResult); 85 extern template void CheckSpecificationExpr(const Expr<SomeInteger> &x, 86 const semantics::Scope &, FoldingContext &, 87 bool forElementalFunctionResult); 88 extern template void CheckSpecificationExpr(const Expr<SubscriptInteger> &x, 89 const semantics::Scope &, FoldingContext &, 90 bool forElementalFunctionResult); 91 extern template void CheckSpecificationExpr( 92 const std::optional<Expr<SomeType>> &x, const semantics::Scope &, 93 FoldingContext &, bool forElementalFunctionResult); 94 extern template void CheckSpecificationExpr( 95 const std::optional<Expr<SomeInteger>> &x, const semantics::Scope &, 96 FoldingContext &, bool forElementalFunctionResult); 97 extern template void CheckSpecificationExpr( 98 const std::optional<Expr<SubscriptInteger>> &x, const semantics::Scope &, 99 FoldingContext &, bool forElementalFunctionResult); 100 101 // Contiguity & "simple contiguity" (9.5.4) 102 template <typename A> 103 std::optional<bool> IsContiguous(const A &, FoldingContext &); 104 extern template std::optional<bool> IsContiguous( 105 const Expr<SomeType> &, FoldingContext &); 106 extern template std::optional<bool> IsContiguous( 107 const ArrayRef &, FoldingContext &); 108 extern template std::optional<bool> IsContiguous( 109 const Substring &, FoldingContext &); 110 extern template std::optional<bool> IsContiguous( 111 const Component &, FoldingContext &); 112 extern template std::optional<bool> IsContiguous( 113 const ComplexPart &, FoldingContext &); 114 extern template std::optional<bool> IsContiguous( 115 const CoarrayRef &, FoldingContext &); 116 extern template std::optional<bool> IsContiguous( 117 const Symbol &, FoldingContext &); 118 static inline std::optional<bool> IsContiguous( 119 const SymbolRef &s, FoldingContext &c) { 120 return IsContiguous(s.get(), c); 121 } 122 template <typename A> 123 bool IsSimplyContiguous(const A &x, FoldingContext &context) { 124 return IsContiguous(x, context).value_or(false); 125 } 126 127 template <typename A> bool IsErrorExpr(const A &); 128 extern template bool IsErrorExpr(const Expr<SomeType> &); 129 130 std::optional<parser::Message> CheckStatementFunction( 131 const Symbol &, const Expr<SomeType> &, FoldingContext &); 132 133 } // namespace Fortran::evaluate 134 #endif 135