xref: /llvm-project/flang/include/flang/Evaluate/check-expression.h (revision 1c6ec29b6bf86709384049660c69cc2d31e356b2)
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