Skip to content

Commit 4171f80

Browse files
committed
[flang] DATA stmt processing (part 3/4): Remaining prep work
Rolls up small changes across the frontend to prepare for the large forthcoming patch (part 4/4) that completes DATA statement processing via conversion to initializers. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D82137
1 parent c4d13f7 commit 4171f80

40 files changed

+700
-304
lines changed

flang/documentation/FortranForCProgrammers.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ byte sizes of the data.
9191
(For `COMPLEX`, the kind type parameter value is the byte size of one of the
9292
two `REAL` components, or half of the total size.)
9393
The legacy `DOUBLE PRECISION` intrinsic type is an alias for a kind of `REAL`
94-
that should be bigger than the default `REAL`.
94+
that should be more precise, and bigger, than the default `REAL`.
9595

9696
`COMPLEX` is a simple structure that comprises two `REAL` components.
9797

@@ -363,3 +363,9 @@ result; e.g., if there is a `PRINT` statement in function `F`, it
363363
may or may not be executed by the assignment statement `X=0*F()`.
364364
(Well, it probably will be, in practice, but compilers always reserve
365365
the right to optimize better.)
366+
367+
Unless they have an explicit suffix (`1.0_8`, `2.0_8`) or a `D`
368+
exponent (`3.0D0`), real literal constants in Fortran have the
369+
default `REAL` type -- *not* `double` as in the case in C and C++.
370+
If you're not careful, you can lose precision at compilation time
371+
from your constant values and never know it.

flang/include/flang/Common/interval.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,26 @@ template <typename A> class Interval {
3131
constexpr Interval &operator=(const Interval &) = default;
3232
constexpr Interval &operator=(Interval &&) = default;
3333

34+
constexpr bool operator<(const Interval &that) const {
35+
return start_ < that.start_ ||
36+
(start_ == that.start_ && size_ < that.size_);
37+
}
38+
constexpr bool operator<=(const Interval &that) const {
39+
return start_ < that.start_ ||
40+
(start_ == that.start_ && size_ <= that.size_);
41+
}
3442
constexpr bool operator==(const Interval &that) const {
3543
return start_ == that.start_ && size_ == that.size_;
3644
}
3745
constexpr bool operator!=(const Interval &that) const {
3846
return !(*this == that);
3947
}
48+
constexpr bool operator>=(const Interval &that) const {
49+
return !(*this < that);
50+
}
51+
constexpr bool operator>(const Interval &that) const {
52+
return !(*this <= that);
53+
}
4054

4155
constexpr const A &start() const { return start_; }
4256
constexpr std::size_t size() const { return size_; }

flang/include/flang/Evaluate/characteristics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ struct Procedure {
278278
const ProcedureRef &, const IntrinsicProcTable &);
279279

280280
// At most one of these will return true.
281-
// For "EXTERNAL P" with no calls to P, both will be false.
281+
// For "EXTERNAL P" with no type for or calls to P, both will be false.
282282
bool IsFunction() const { return functionResult.has_value(); }
283283
bool IsSubroutine() const { return attrs.test(Attr::Subroutine); }
284284

flang/include/flang/Evaluate/check-expression.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,19 @@ template <typename A> bool IsConstantExpr(const A &);
3333
extern template bool IsConstantExpr(const Expr<SomeType> &);
3434
extern template bool IsConstantExpr(const Expr<SomeInteger> &);
3535
extern template bool IsConstantExpr(const Expr<SubscriptInteger> &);
36+
extern template bool IsConstantExpr(const StructureConstructor &);
3637

3738
// Checks whether an expression is an object designator with
3839
// constant addressing and no vector-valued subscript.
40+
// If a non-null ContextualMessages pointer is passed, an error message
41+
// will be generated if and only if the result of the function is false.
3942
bool IsInitialDataTarget(
4043
const Expr<SomeType> &, parser::ContextualMessages * = nullptr);
4144

45+
bool IsInitialProcedureTarget(const Symbol &);
46+
bool IsInitialProcedureTarget(const ProcedureDesignator &);
47+
bool IsInitialProcedureTarget(const Expr<SomeType> &);
48+
4249
// Check whether an expression is a specification expression
4350
// (10.1.11(2), C1010). Constant expressions are always valid
4451
// specification expressions.

flang/include/flang/Evaluate/constant.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ using SymbolRef = common::Reference<const Symbol>;
3232
// Wraps a constant value in a class templated by its resolved type.
3333
// This Constant<> template class should be instantiated only for
3434
// concrete intrinsic types and SomeDerived. There is no instance
35-
// Constant<Expr<SomeType>> since there is no way to constrain each
35+
// Constant<SomeType> since there is no way to constrain each
3636
// element of its array to hold the same type. To represent a generic
37-
// constants, use a generic expression like Expr<SomeInteger> &
37+
// constant, use a generic expression like Expr<SomeInteger> or
3838
// Expr<SomeType>) to wrap the appropriate instantiation of Constant<>.
3939

4040
template <typename> class Constant;
@@ -50,7 +50,7 @@ std::size_t TotalElementCount(const ConstantSubscripts &);
5050

5151
// Validate dimension re-ordering like ORDER in RESHAPE.
5252
// On success, return a vector that can be used as dimOrder in
53-
// ConstantBound::IncrementSubscripts.
53+
// ConstantBound::IncrementSubscripts().
5454
std::optional<std::vector<int>> ValidateDimensionOrder(
5555
int rank, const std::vector<int> &order);
5656

@@ -71,8 +71,8 @@ class ConstantBounds {
7171
// If no optional dimension order argument is passed, increments a vector of
7272
// subscripts in Fortran array order (first dimension varying most quickly).
7373
// Otherwise, increments the vector of subscripts according to the given
74-
// dimension order (dimension dimOrder[0] varying most quickly. Dimensions
75-
// indexing is zero based here.) Returns false when last element was visited.
74+
// dimension order (dimension dimOrder[0] varying most quickly; dimension
75+
// indexing is zero based here). Returns false when last element was visited.
7676
bool IncrementSubscripts(
7777
ConstantSubscripts &, const std::vector<int> *dimOrder = nullptr) const;
7878

@@ -158,7 +158,8 @@ class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds {
158158
CLASS_BOILERPLATE(Constant)
159159
explicit Constant(const Scalar<Result> &);
160160
explicit Constant(Scalar<Result> &&);
161-
Constant(ConstantSubscript, std::vector<Element> &&, ConstantSubscripts &&);
161+
Constant(
162+
ConstantSubscript length, std::vector<Element> &&, ConstantSubscripts &&);
162163
~Constant();
163164

164165
bool operator==(const Constant &that) const {
@@ -191,8 +192,6 @@ class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds {
191192
private:
192193
Scalar<Result> values_; // one contiguous string
193194
ConstantSubscript length_;
194-
ConstantSubscripts shape_;
195-
ConstantSubscripts lbounds_;
196195
};
197196

198197
class StructureConstructor;

flang/include/flang/Evaluate/fold.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define FORTRAN_EVALUATE_FOLD_H_
1111

1212
// Implements expression tree rewriting, particularly constant expression
13-
// evaluation.
13+
// and designator reference evaluation.
1414

1515
#include "common.h"
1616
#include "constant.h"

flang/include/flang/Evaluate/tools.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,7 @@ bool IsDummy(const Symbol &);
913913
const Symbol *GetAssociationRoot(const Symbol &);
914914
const Symbol *FindCommonBlockContaining(const Symbol &);
915915
int CountLenParameters(const DerivedTypeSpec &);
916+
int CountNonConstantLenParameters(const DerivedTypeSpec &);
916917
const Symbol &GetUsedModule(const UseDetails &);
917918

918919
} // namespace Fortran::semantics

flang/include/flang/Parser/parse-tree.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,15 +1400,16 @@ using TypedExpr = std::unique_ptr<evaluate::GenericExprWrapper,
14001400
// R845 data-stmt-constant ->
14011401
// scalar-constant | scalar-constant-subobject |
14021402
// signed-int-literal-constant | signed-real-literal-constant |
1403-
// null-init | initial-data-target | structure-constructor
1403+
// null-init | initial-data-target |
1404+
// constant-structure-constructor <- added "constant-"
14041405
struct DataStmtConstant {
14051406
UNION_CLASS_BOILERPLATE(DataStmtConstant);
14061407
CharBlock source;
14071408
mutable TypedExpr typedExpr;
14081409
std::variant<Scalar<ConstantValue>, Scalar<ConstantSubobject>,
14091410
SignedIntLiteralConstant, SignedRealLiteralConstant,
14101411
SignedComplexLiteralConstant, NullInit, InitialDataTarget,
1411-
StructureConstructor>
1412+
Constant<StructureConstructor>>
14121413
u;
14131414
};
14141415

@@ -1424,6 +1425,7 @@ struct DataStmtRepeat {
14241425
// R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant
14251426
struct DataStmtValue {
14261427
TUPLE_CLASS_BOILERPLATE(DataStmtValue);
1428+
mutable std::size_t repetitions{1}; // replaced during semantics
14271429
std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t;
14281430
};
14291431

flang/include/flang/Parser/tools.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ const Name &GetLastName(const FunctionReference &);
2828
const Name &GetLastName(const Variable &);
2929
const Name &GetLastName(const AllocateObject &);
3030

31+
// GetFirstName() isolates and returns a reference to the leftmost Name
32+
// in a variable.
33+
const Name &GetFirstName(const Name &);
34+
const Name &GetFirstName(const StructureComponent &);
35+
const Name &GetFirstName(const DataRef &);
36+
const Name &GetFirstName(const Substring &);
37+
const Name &GetFirstName(const Designator &);
38+
const Name &GetFirstName(const ProcComponentRef &);
39+
const Name &GetFirstName(const ProcedureDesignator &);
40+
const Name &GetFirstName(const Call &);
41+
const Name &GetFirstName(const FunctionReference &);
42+
const Name &GetFirstName(const Variable &);
43+
3144
// When a parse tree node is an instance of a specific type wrapped in
3245
// layers of packaging, return a pointer to that object.
3346
// Implemented with mutually recursive template functions that are

flang/include/flang/Semantics/expression.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,11 @@ class ExpressionAnalyzer {
131131
bool CheckIntrinsicSize(TypeCategory, std::int64_t size);
132132

133133
// Manage a set of active implied DO loops.
134-
bool AddImpliedDo(parser::CharBlock, int);
134+
bool AddImpliedDo(parser::CharBlock, int kind);
135135
void RemoveImpliedDo(parser::CharBlock);
136+
137+
// When the argument is the name of an active implied DO index, returns
138+
// its INTEGER kind type parameter.
136139
std::optional<int> IsImpliedDo(parser::CharBlock) const;
137140

138141
Expr<SubscriptInteger> AnalyzeKindSelector(common::TypeCategory category,
@@ -141,7 +144,7 @@ class ExpressionAnalyzer {
141144
MaybeExpr Analyze(const parser::Expr &);
142145
MaybeExpr Analyze(const parser::Variable &);
143146
MaybeExpr Analyze(const parser::Designator &);
144-
MaybeExpr Analyze(const parser::DataStmtConstant &);
147+
MaybeExpr Analyze(const parser::DataStmtValue &);
145148

146149
template <typename A> MaybeExpr Analyze(const common::Indirection<A> &x) {
147150
return Analyze(x.value());
@@ -241,6 +244,7 @@ class ExpressionAnalyzer {
241244
MaybeExpr Analyze(const parser::BOZLiteralConstant &);
242245
MaybeExpr Analyze(const parser::NamedConstant &);
243246
MaybeExpr Analyze(const parser::NullInit &);
247+
MaybeExpr Analyze(const parser::DataStmtConstant &);
244248
MaybeExpr Analyze(const parser::Substring &);
245249
MaybeExpr Analyze(const parser::ArrayElement &);
246250
MaybeExpr Analyze(const parser::CoindexedNamedObject &);
@@ -420,17 +424,19 @@ class ExprChecker {
420424
bool Walk(const parser::Program &);
421425

422426
bool Pre(const parser::Expr &x) {
423-
AnalyzeExpr(context_, x);
427+
exprAnalyzer_.Analyze(x);
424428
return false;
425429
}
426430
bool Pre(const parser::Variable &x) {
427-
AnalyzeExpr(context_, x);
431+
exprAnalyzer_.Analyze(x);
428432
return false;
429433
}
430-
bool Pre(const parser::DataStmtConstant &x) {
431-
AnalyzeExpr(context_, x);
434+
bool Pre(const parser::DataStmtValue &x) {
435+
exprAnalyzer_.Analyze(x);
432436
return false;
433437
}
438+
bool Pre(const parser::DataImpliedDo &);
439+
434440
bool Pre(const parser::CallStmt &x) {
435441
AnalyzeCallStmt(context_, x);
436442
return false;
@@ -445,28 +451,29 @@ class ExprChecker {
445451
}
446452

447453
template <typename A> bool Pre(const parser::Scalar<A> &x) {
448-
AnalyzeExpr(context_, x);
454+
exprAnalyzer_.Analyze(x);
449455
return false;
450456
}
451457
template <typename A> bool Pre(const parser::Constant<A> &x) {
452-
AnalyzeExpr(context_, x);
458+
exprAnalyzer_.Analyze(x);
453459
return false;
454460
}
455461
template <typename A> bool Pre(const parser::Integer<A> &x) {
456-
AnalyzeExpr(context_, x);
462+
exprAnalyzer_.Analyze(x);
457463
return false;
458464
}
459465
template <typename A> bool Pre(const parser::Logical<A> &x) {
460-
AnalyzeExpr(context_, x);
466+
exprAnalyzer_.Analyze(x);
461467
return false;
462468
}
463469
template <typename A> bool Pre(const parser::DefaultChar<A> &x) {
464-
AnalyzeExpr(context_, x);
470+
exprAnalyzer_.Analyze(x);
465471
return false;
466472
}
467473

468474
private:
469475
SemanticsContext &context_;
476+
evaluate::ExpressionAnalyzer exprAnalyzer_{context_};
470477
};
471478
} // namespace Fortran::semantics
472479
#endif // FORTRAN_SEMANTICS_EXPRESSION_H_

0 commit comments

Comments
 (0)