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.
31// The FoldingContext pointer, if not null, prevents a "free" implied
32// DO index from being allowed in a constant expression or initial data
33// target if it is not registered in the FoldingContext. (Array constructor
34// implied DO indices are always allowed when the implied DO is within
35// the expression.)
36template <typename A>
37bool IsConstantExpr(const A &, const FoldingContext * = nullptr);
38extern template bool IsConstantExpr(
39 const Expr<SomeType> &, const FoldingContext *);
40extern template bool IsConstantExpr(
41 const Expr<SomeInteger> &, const FoldingContext *);
42extern template bool IsConstantExpr(
43 const Expr<SubscriptInteger> &, const FoldingContext *);
44extern template bool IsConstantExpr(
45 const StructureConstructor &, const FoldingContext *);
46
47// Predicate: true when an expression is a constant expression (in the
48// strict sense of the Fortran standard) or a dummy argument with
49// INTENT(IN) and no VALUE. This is useful for representing explicit
50// shapes of other dummy arguments.
51template <typename A>
52bool IsScopeInvariantExpr(const A &, const FoldingContext * = nullptr);
53extern template bool IsScopeInvariantExpr(
54 const Expr<SomeType> &, const FoldingContext *);
55extern template bool IsScopeInvariantExpr(
56 const Expr<SomeInteger> &, const FoldingContext *);
57extern template bool IsScopeInvariantExpr(
58 const Expr<SubscriptInteger> &, const FoldingContext *);
59
60// Predicate: true when an expression actually is a typed Constant<T>,
61// perhaps with parentheses and wrapping around it. False for all typeless
62// expressions, including BOZ literals.
63template <typename A> bool IsActuallyConstant(const A &);
64extern template bool IsActuallyConstant(const Expr<SomeType> &);
65extern template bool IsActuallyConstant(const Expr<SomeInteger> &);
66extern template bool IsActuallyConstant(const Expr<SubscriptInteger> &);
67extern template bool IsActuallyConstant(
68 const std::optional<Expr<SubscriptInteger>> &);
69
70// Checks whether an expression is an object designator with
71// constant addressing and no vector-valued subscript.
72// If a non-null ContextualMessages pointer is passed, an error message
73// will be generated if and only if the result of the function is false.
74bool IsInitialDataTarget(const Expr<SomeType> &,
75 parser::ContextualMessages * = nullptr, const FoldingContext * = nullptr);
76
77bool IsInitialProcedureTarget(const Symbol &);
78bool IsInitialProcedureTarget(const ProcedureDesignator &);
79bool IsInitialProcedureTarget(const Expr<SomeType> &);
80
81// Emit warnings about default REAL literal constants in contexts that
82// will be converted to a higher precision REAL kind than the default.
83void CheckRealWidening(
84 const Expr<SomeType> &, const DynamicType &toType, FoldingContext &);
85void CheckRealWidening(const Expr<SomeType> &,
86 const std::optional<DynamicType> &, FoldingContext &);
87
88// Validate the value of a named constant, the static initial
89// value of a non-pointer non-allocatable non-dummy variable, or the
90// default initializer of a component of a derived type (or instantiation
91// of a derived type). Converts type and expands scalars as necessary.
92std::optional<Expr<SomeType>> NonPointerInitializationExpr(const Symbol &,
93 Expr<SomeType> &&, FoldingContext &,
94 const semantics::Scope *instantiation = nullptr);
95
96// Check whether an expression is a specification expression
97// (10.1.11(2), C1010). Constant expressions are always valid
98// specification expressions.
99
100template <typename A>
101void CheckSpecificationExpr(const A &, const semantics::Scope &,
102 FoldingContext &, bool forElementalFunctionResult);
103extern template void CheckSpecificationExpr(const Expr<SomeType> &x,
104 const semantics::Scope &, FoldingContext &,
105 bool forElementalFunctionResult);
106extern template void CheckSpecificationExpr(const Expr<SomeInteger> &x,
107 const semantics::Scope &, FoldingContext &,
108 bool forElementalFunctionResult);
109extern template void CheckSpecificationExpr(const Expr<SubscriptInteger> &x,
110 const semantics::Scope &, FoldingContext &,
111 bool forElementalFunctionResult);
112extern template void CheckSpecificationExpr(
113 const std::optional<Expr<SomeType>> &x, const semantics::Scope &,
114 FoldingContext &, bool forElementalFunctionResult);
115extern template void CheckSpecificationExpr(
116 const std::optional<Expr<SomeInteger>> &x, const semantics::Scope &,
117 FoldingContext &, bool forElementalFunctionResult);
118extern template void CheckSpecificationExpr(
119 const std::optional<Expr<SubscriptInteger>> &x, const semantics::Scope &,
120 FoldingContext &, bool forElementalFunctionResult);
121
122// Contiguity & "simple contiguity" (9.5.4)
123// Named constant sections are expressions, and as such their evaluation is
124// considered to be contiguous. This avoids funny situations where
125// IS_CONTIGUOUS(cst(1:10:2)) would fold to true because `cst(1:10:2)` is
126// folded into an array constructor literal, but IS_CONTIGUOUS(cst(i:i+9:2))
127// folds to false because the named constant reference cannot be folded.
128// Note that these IS_CONTIGUOUS usages are not portable (can probably be
129// considered to fall into F2023 8.5.7 (4)), and existing compilers are not
130// consistent here.
131// However, the compiler may very well decide to create a descriptor over
132// `cst(i:i+9:2)` when it can to avoid copies, and as such it needs internally
133// to be able to tell the actual contiguity of that array section over the
134// read-only data.
135template <typename A>
136std::optional<bool> IsContiguous(const A &, FoldingContext &,
137 bool namedConstantSectionsAreContiguous = true,
138 bool firstDimensionStride1 = false);
139extern template std::optional<bool> IsContiguous(const Expr<SomeType> &,
140 FoldingContext &, bool namedConstantSectionsAreContiguous,
141 bool firstDimensionStride1);
142extern template std::optional<bool> IsContiguous(const ActualArgument &,
143 FoldingContext &, bool namedConstantSectionsAreContiguous,
144 bool firstDimensionStride1);
145extern template std::optional<bool> IsContiguous(const ArrayRef &,
146 FoldingContext &, bool namedConstantSectionsAreContiguous,
147 bool firstDimensionStride1);
148extern template std::optional<bool> IsContiguous(const Substring &,
149 FoldingContext &, bool namedConstantSectionsAreContiguous,
150 bool firstDimensionStride1);
151extern template std::optional<bool> IsContiguous(const Component &,
152 FoldingContext &, bool namedConstantSectionsAreContiguous,
153 bool firstDimensionStride1);
154extern template std::optional<bool> IsContiguous(const ComplexPart &,
155 FoldingContext &, bool namedConstantSectionsAreContiguous,
156 bool firstDimensionStride1);
157extern template std::optional<bool> IsContiguous(const CoarrayRef &,
158 FoldingContext &, bool namedConstantSectionsAreContiguous,
159 bool firstDimensionStride1);
160extern template std::optional<bool> IsContiguous(const Symbol &,
161 FoldingContext &, bool namedConstantSectionsAreContiguous,
162 bool firstDimensionStride1);
163static inline std::optional<bool> IsContiguous(const SymbolRef &s,
164 FoldingContext &c, bool namedConstantSectionsAreContiguous = true) {
165 return IsContiguous(s.get(), c, namedConstantSectionsAreContiguous);
166}
167template <typename A>
168bool IsSimplyContiguous(const A &x, FoldingContext &context,
169 bool namedConstantSectionsAreContiguous = true) {
170 return IsContiguous(x, context, namedConstantSectionsAreContiguous)
171 .value_or(false);
172}
173
174template <typename A> bool IsErrorExpr(const A &);
175extern template bool IsErrorExpr(const Expr<SomeType> &);
176
177std::optional<parser::Message> CheckStatementFunction(
178 const Symbol &, const Expr<SomeType> &, FoldingContext &);
179
180std::optional<bool> ActualArgNeedsCopy(const ActualArgument *,
181 const characteristics::DummyArgument *, FoldingContext &, bool forCopyOut);
182
183} // namespace Fortran::evaluate
184#endif
Definition common.h:214
Definition common.h:216
Definition message.h:396
Definition symbol.h:809
Definition call.h:34
Definition check-expression.h:19