FLANG
check-expression.h
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
19namespace Fortran::parser {
21}
22namespace Fortran::semantics {
23class Scope;
24}
25
26namespace 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.
31template <typename A> bool IsConstantExpr(const A &);
32extern template bool IsConstantExpr(const Expr<SomeType> &);
33extern template bool IsConstantExpr(const Expr<SomeInteger> &);
34extern template bool IsConstantExpr(const Expr<SubscriptInteger> &);
35extern 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.
41template <typename A> bool IsScopeInvariantExpr(const A &);
42extern template bool IsScopeInvariantExpr(const Expr<SomeType> &);
43extern template bool IsScopeInvariantExpr(const Expr<SomeInteger> &);
44extern 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.
49template <typename A> bool IsActuallyConstant(const A &);
50extern template bool IsActuallyConstant(const Expr<SomeType> &);
51extern template bool IsActuallyConstant(const Expr<SomeInteger> &);
52extern template bool IsActuallyConstant(const Expr<SubscriptInteger> &);
53extern 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.
60bool IsInitialDataTarget(
61 const Expr<SomeType> &, parser::ContextualMessages * = nullptr);
62
63bool IsInitialProcedureTarget(const Symbol &);
64bool IsInitialProcedureTarget(const ProcedureDesignator &);
65bool IsInitialProcedureTarget(const Expr<SomeType> &);
66
67// Emit warnings about default REAL literal constants in contexts that
68// will be converted to a higher precision REAL kind than the default.
69void CheckRealWidening(
70 const Expr<SomeType> &, const DynamicType &toType, FoldingContext &);
71void CheckRealWidening(const Expr<SomeType> &,
72 const std::optional<DynamicType> &, FoldingContext &);
73
74// Validate the value of a named constant, the static initial
75// value of a non-pointer non-allocatable non-dummy variable, or the
76// default initializer of a component of a derived type (or instantiation
77// of a derived type). Converts type and expands scalars as necessary.
78std::optional<Expr<SomeType>> NonPointerInitializationExpr(const Symbol &,
79 Expr<SomeType> &&, FoldingContext &,
80 const semantics::Scope *instantiation = nullptr);
81
82// Check whether an expression is a specification expression
83// (10.1.11(2), C1010). Constant expressions are always valid
84// specification expressions.
85
86template <typename A>
87void CheckSpecificationExpr(const A &, const semantics::Scope &,
88 FoldingContext &, bool forElementalFunctionResult);
89extern template void CheckSpecificationExpr(const Expr<SomeType> &x,
90 const semantics::Scope &, FoldingContext &,
91 bool forElementalFunctionResult);
92extern template void CheckSpecificationExpr(const Expr<SomeInteger> &x,
93 const semantics::Scope &, FoldingContext &,
94 bool forElementalFunctionResult);
95extern template void CheckSpecificationExpr(const Expr<SubscriptInteger> &x,
96 const semantics::Scope &, FoldingContext &,
97 bool forElementalFunctionResult);
98extern template void CheckSpecificationExpr(
99 const std::optional<Expr<SomeType>> &x, const semantics::Scope &,
100 FoldingContext &, bool forElementalFunctionResult);
101extern template void CheckSpecificationExpr(
102 const std::optional<Expr<SomeInteger>> &x, const semantics::Scope &,
103 FoldingContext &, bool forElementalFunctionResult);
104extern template void CheckSpecificationExpr(
105 const std::optional<Expr<SubscriptInteger>> &x, const semantics::Scope &,
106 FoldingContext &, bool forElementalFunctionResult);
107
108// Contiguity & "simple contiguity" (9.5.4)
109// Named constant sections are expressions, and as such their evaluation is
110// considered to be contiguous. This avoids funny situations where
111// IS_CONTIGUOUS(cst(1:10:2)) would fold to true because `cst(1:10:2)` is
112// folded into an array constructor literal, but IS_CONTIGUOUS(cst(i:i+9:2))
113// folds to false because the named constant reference cannot be folded.
114// Note that these IS_CONTIGUOUS usages are not portable (can probably be
115// considered to fall into F2023 8.5.7 (4)), and existing compilers are not
116// consistent here.
117// However, the compiler may very well decide to create a descriptor over
118// `cst(i:i+9:2)` when it can to avoid copies, and as such it needs internally
119// to be able to tell the actual contiguity of that array section over the
120// read-only data.
121template <typename A>
122std::optional<bool> IsContiguous(const A &, FoldingContext &,
123 bool namedConstantSectionsAreContiguous = true,
124 bool firstDimensionStride1 = false);
125extern template std::optional<bool> IsContiguous(const Expr<SomeType> &,
126 FoldingContext &, bool namedConstantSectionsAreContiguous,
127 bool firstDimensionStride1);
128extern template std::optional<bool> IsContiguous(const ActualArgument &,
129 FoldingContext &, bool namedConstantSectionsAreContiguous,
130 bool firstDimensionStride1);
131extern template std::optional<bool> IsContiguous(const ArrayRef &,
132 FoldingContext &, bool namedConstantSectionsAreContiguous,
133 bool firstDimensionStride1);
134extern template std::optional<bool> IsContiguous(const Substring &,
135 FoldingContext &, bool namedConstantSectionsAreContiguous,
136 bool firstDimensionStride1);
137extern template std::optional<bool> IsContiguous(const Component &,
138 FoldingContext &, bool namedConstantSectionsAreContiguous,
139 bool firstDimensionStride1);
140extern template std::optional<bool> IsContiguous(const ComplexPart &,
141 FoldingContext &, bool namedConstantSectionsAreContiguous,
142 bool firstDimensionStride1);
143extern template std::optional<bool> IsContiguous(const CoarrayRef &,
144 FoldingContext &, bool namedConstantSectionsAreContiguous,
145 bool firstDimensionStride1);
146extern template std::optional<bool> IsContiguous(const Symbol &,
147 FoldingContext &, bool namedConstantSectionsAreContiguous,
148 bool firstDimensionStride1);
149static inline std::optional<bool> IsContiguous(const SymbolRef &s,
150 FoldingContext &c, bool namedConstantSectionsAreContiguous = true) {
151 return IsContiguous(s.get(), c, namedConstantSectionsAreContiguous);
152}
153template <typename A>
154bool IsSimplyContiguous(const A &x, FoldingContext &context,
155 bool namedConstantSectionsAreContiguous = true) {
156 return IsContiguous(x, context, namedConstantSectionsAreContiguous)
157 .value_or(false);
158}
159
160template <typename A> bool IsErrorExpr(const A &);
161extern template bool IsErrorExpr(const Expr<SomeType> &);
162
163std::optional<parser::Message> CheckStatementFunction(
164 const Symbol &, const Expr<SomeType> &, FoldingContext &);
165
166bool MayNeedCopy(const ActualArgument *, const characteristics::DummyArgument *,
167 FoldingContext &, bool forCopyOut);
168
169} // namespace Fortran::evaluate
170#endif
Definition common.h:214
Definition common.h:216
Definition message.h:384
Definition symbol.h:778
Definition call.h:34
Definition check-expression.h:19