|
7 | 7 |
|
8 | 8 | #include "resolve-names.h"
|
9 | 9 | #include "assignment.h"
|
| 10 | +#include "data-to-inits.h" |
10 | 11 | #include "definable.h"
|
11 | 12 | #include "mod-file.h"
|
12 | 13 | #include "pointer-assignment.h"
|
@@ -1085,8 +1086,12 @@ class DeclarationVisitor : public ArraySpecVisitor,
|
1085 | 1086 | const parser::Name &, const parser::InitialDataTarget &);
|
1086 | 1087 | void PointerInitialization(
|
1087 | 1088 | const parser::Name &, const parser::ProcPointerInit &);
|
| 1089 | + bool CheckNonPointerInitialization( |
| 1090 | + const parser::Name &, bool inLegacyDataInitialization); |
1088 | 1091 | void NonPointerInitialization(
|
1089 | 1092 | const parser::Name &, const parser::ConstantExpr &);
|
| 1093 | + void LegacyDataInitialization(const parser::Name &, |
| 1094 | + const std::list<common::Indirection<parser::DataStmtValue>> &values); |
1090 | 1095 | void CheckExplicitInterface(const parser::Name &);
|
1091 | 1096 | void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);
|
1092 | 1097 |
|
@@ -9029,6 +9034,14 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
|
9029 | 9034 | ultimate.set(Symbol::Flag::InDataStmt);
|
9030 | 9035 | }
|
9031 | 9036 | },
|
| 9037 | + [&](const std::list<Indirection<parser::DataStmtValue>> &values) { |
| 9038 | + Walk(values); |
| 9039 | + if (inComponentDecl) { |
| 9040 | + LegacyDataInitialization(name, values); |
| 9041 | + } else { |
| 9042 | + ultimate.set(Symbol::Flag::InDataStmt); |
| 9043 | + } |
| 9044 | + }, |
9032 | 9045 | [&](const parser::NullInit &null) { // => NULL()
|
9033 | 9046 | Walk(null);
|
9034 | 9047 | if (auto nullInit{EvaluateExpr(null)}) {
|
@@ -9062,11 +9075,6 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
|
9062 | 9075 | ultimate.set(Symbol::Flag::InDataStmt);
|
9063 | 9076 | }
|
9064 | 9077 | },
|
9065 |
| - [&](const std::list<Indirection<parser::DataStmtValue>> &values) { |
9066 |
| - // Handled later in data-to-inits conversion |
9067 |
| - ultimate.set(Symbol::Flag::InDataStmt); |
9068 |
| - Walk(values); |
9069 |
| - }, |
9070 | 9078 | },
|
9071 | 9079 | init.u);
|
9072 | 9080 | }
|
@@ -9137,36 +9145,82 @@ void DeclarationVisitor::PointerInitialization(
|
9137 | 9145 | }
|
9138 | 9146 | }
|
9139 | 9147 |
|
9140 |
| -void DeclarationVisitor::NonPointerInitialization( |
9141 |
| - const parser::Name &name, const parser::ConstantExpr &expr) { |
| 9148 | +bool DeclarationVisitor::CheckNonPointerInitialization( |
| 9149 | + const parser::Name &name, bool inLegacyDataInitialization) { |
9142 | 9150 | if (!context().HasError(name.symbol)) {
|
9143 | 9151 | Symbol &ultimate{name.symbol->GetUltimate()};
|
9144 | 9152 | if (!context().HasError(ultimate)) {
|
9145 |
| - if (IsPointer(ultimate)) { |
| 9153 | + if (IsPointer(ultimate) && !inLegacyDataInitialization) { |
9146 | 9154 | Say(name,
|
9147 | 9155 | "'%s' is a pointer but is not initialized like one"_err_en_US);
|
9148 | 9156 | } else if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {
|
9149 | 9157 | if (details->init()) {
|
9150 | 9158 | SayWithDecl(name, *name.symbol,
|
9151 | 9159 | "'%s' has already been initialized"_err_en_US);
|
9152 |
| - } else if (details->isCDefined()) { |
9153 |
| - context().Warn(common::UsageWarning::CdefinedInit, name.source, |
9154 |
| - "CDEFINED variable should not have an initializer"_warn_en_US); |
9155 | 9160 | } else if (IsAllocatable(ultimate)) {
|
9156 | 9161 | Say(name, "Allocatable object '%s' cannot be initialized"_err_en_US);
|
9157 |
| - } else if (ultimate.owner().IsParameterizedDerivedType()) { |
9158 |
| - // Save the expression for per-instantiation analysis. |
9159 |
| - details->set_unanalyzedPDTComponentInit(&expr.thing.value()); |
9160 |
| - } else if (MaybeExpr folded{EvaluateNonPointerInitializer( |
9161 |
| - ultimate, expr, expr.thing.value().source)}) { |
9162 |
| - details->set_init(std::move(*folded)); |
9163 |
| - ultimate.set(Symbol::Flag::InDataStmt, false); |
| 9162 | + } else { |
| 9163 | + if (details->isCDefined()) { |
| 9164 | + context().Warn(common::UsageWarning::CdefinedInit, name.source, |
| 9165 | + "CDEFINED variable should not have an initializer"_warn_en_US); |
| 9166 | + } |
| 9167 | + return true; |
9164 | 9168 | }
|
9165 | 9169 | } else {
|
9166 | 9170 | Say(name, "'%s' is not an object that can be initialized"_err_en_US);
|
9167 | 9171 | }
|
9168 | 9172 | }
|
9169 | 9173 | }
|
| 9174 | + return false; |
| 9175 | +} |
| 9176 | + |
| 9177 | +void DeclarationVisitor::NonPointerInitialization( |
| 9178 | + const parser::Name &name, const parser::ConstantExpr &expr) { |
| 9179 | + if (CheckNonPointerInitialization( |
| 9180 | + name, /*inLegacyDataInitialization=*/false)) { |
| 9181 | + Symbol &ultimate{name.symbol->GetUltimate()}; |
| 9182 | + auto &details{ultimate.get<ObjectEntityDetails>()}; |
| 9183 | + if (ultimate.owner().IsParameterizedDerivedType()) { |
| 9184 | + // Save the expression for per-instantiation analysis. |
| 9185 | + details.set_unanalyzedPDTComponentInit(&expr.thing.value()); |
| 9186 | + } else if (MaybeExpr folded{EvaluateNonPointerInitializer( |
| 9187 | + ultimate, expr, expr.thing.value().source)}) { |
| 9188 | + details.set_init(std::move(*folded)); |
| 9189 | + ultimate.set(Symbol::Flag::InDataStmt, false); |
| 9190 | + } |
| 9191 | + } |
| 9192 | +} |
| 9193 | + |
| 9194 | +void DeclarationVisitor::LegacyDataInitialization(const parser::Name &name, |
| 9195 | + const std::list<common::Indirection<parser::DataStmtValue>> &values) { |
| 9196 | + if (CheckNonPointerInitialization( |
| 9197 | + name, /*inLegacyDataInitialization=*/true)) { |
| 9198 | + Symbol &ultimate{name.symbol->GetUltimate()}; |
| 9199 | + if (ultimate.owner().IsParameterizedDerivedType()) { |
| 9200 | + Say(name, |
| 9201 | + "Component '%s' in a parameterized data type may not be initialized with a legacy DATA-style value list"_err_en_US, |
| 9202 | + name.source); |
| 9203 | + } else { |
| 9204 | + evaluate::ExpressionAnalyzer exprAnalyzer{context()}; |
| 9205 | + for (const auto &value : values) { |
| 9206 | + exprAnalyzer.Analyze(value.value()); |
| 9207 | + } |
| 9208 | + DataInitializations inits; |
| 9209 | + auto oldSize{ultimate.size()}; |
| 9210 | + if (auto chars{evaluate::characteristics::TypeAndShape::Characterize( |
| 9211 | + ultimate, GetFoldingContext())}) { |
| 9212 | + if (auto size{evaluate::ToInt64( |
| 9213 | + chars->MeasureSizeInBytes(GetFoldingContext()))}) { |
| 9214 | + // Temporarily set the byte size of the component so that we don't |
| 9215 | + // get bogus "initialization out of range" errors below. |
| 9216 | + ultimate.set_size(*size); |
| 9217 | + } |
| 9218 | + } |
| 9219 | + AccumulateDataInitializations(inits, exprAnalyzer, ultimate, values); |
| 9220 | + ConvertToInitializers(inits, exprAnalyzer); |
| 9221 | + ultimate.set_size(oldSize); |
| 9222 | + } |
| 9223 | + } |
9170 | 9224 | }
|
9171 | 9225 |
|
9172 | 9226 | void ResolveNamesVisitor::HandleCall(
|
@@ -10516,12 +10570,16 @@ class DeferredCheckVisitor {
|
10516 | 10570 | if (const auto *target{
|
10517 | 10571 | std::get_if<parser::InitialDataTarget>(&init->u)}) {
|
10518 | 10572 | resolver_.PointerInitialization(name, *target);
|
10519 |
| - } else if (const auto *expr{ |
10520 |
| - std::get_if<parser::ConstantExpr>(&init->u)}) { |
10521 |
| - if (name.symbol) { |
10522 |
| - if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()}; |
10523 |
| - !object || !object->init()) { |
| 10573 | + } else if (name.symbol) { |
| 10574 | + if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()}; |
| 10575 | + !object || !object->init()) { |
| 10576 | + if (const auto *expr{std::get_if<parser::ConstantExpr>(&init->u)}) { |
10524 | 10577 | resolver_.NonPointerInitialization(name, *expr);
|
| 10578 | + } else { |
| 10579 | + // Don't check legacy DATA /initialization/ here. Component |
| 10580 | + // initializations will have already been handled, and variable |
| 10581 | + // initializations need to be done in DATA checking so that |
| 10582 | + // EQUIVALENCE storage association can be handled. |
10525 | 10583 | }
|
10526 | 10584 | }
|
10527 | 10585 | }
|
|
0 commit comments