|
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"
|
@@ -1081,8 +1082,12 @@ class DeclarationVisitor : public ArraySpecVisitor,
|
1081 | 1082 | const parser::Name &, const parser::InitialDataTarget &);
|
1082 | 1083 | void PointerInitialization(
|
1083 | 1084 | const parser::Name &, const parser::ProcPointerInit &);
|
| 1085 | + bool CheckNonPointerInitialization( |
| 1086 | + const parser::Name &, bool inLegacyDataInitialization); |
1084 | 1087 | void NonPointerInitialization(
|
1085 | 1088 | const parser::Name &, const parser::ConstantExpr &);
|
| 1089 | + void LegacyDataInitialization(const parser::Name &, |
| 1090 | + const std::list<common::Indirection<parser::DataStmtValue>> &values); |
1086 | 1091 | void CheckExplicitInterface(const parser::Name &);
|
1087 | 1092 | void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);
|
1088 | 1093 |
|
@@ -8995,6 +9000,14 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
|
8995 | 9000 | ultimate.set(Symbol::Flag::InDataStmt);
|
8996 | 9001 | }
|
8997 | 9002 | },
|
| 9003 | + [&](const std::list<Indirection<parser::DataStmtValue>> &values) { |
| 9004 | + Walk(values); |
| 9005 | + if (inComponentDecl) { |
| 9006 | + LegacyDataInitialization(name, values); |
| 9007 | + } else { |
| 9008 | + ultimate.set(Symbol::Flag::InDataStmt); |
| 9009 | + } |
| 9010 | + }, |
8998 | 9011 | [&](const parser::NullInit &null) { // => NULL()
|
8999 | 9012 | Walk(null);
|
9000 | 9013 | if (auto nullInit{EvaluateExpr(null)}) {
|
@@ -9028,11 +9041,6 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
|
9028 | 9041 | ultimate.set(Symbol::Flag::InDataStmt);
|
9029 | 9042 | }
|
9030 | 9043 | },
|
9031 |
| - [&](const std::list<Indirection<parser::DataStmtValue>> &values) { |
9032 |
| - // Handled later in data-to-inits conversion |
9033 |
| - ultimate.set(Symbol::Flag::InDataStmt); |
9034 |
| - Walk(values); |
9035 |
| - }, |
9036 | 9044 | },
|
9037 | 9045 | init.u);
|
9038 | 9046 | }
|
@@ -9103,36 +9111,82 @@ void DeclarationVisitor::PointerInitialization(
|
9103 | 9111 | }
|
9104 | 9112 | }
|
9105 | 9113 |
|
9106 |
| -void DeclarationVisitor::NonPointerInitialization( |
9107 |
| - const parser::Name &name, const parser::ConstantExpr &expr) { |
| 9114 | +bool DeclarationVisitor::CheckNonPointerInitialization( |
| 9115 | + const parser::Name &name, bool inLegacyDataInitialization) { |
9108 | 9116 | if (!context().HasError(name.symbol)) {
|
9109 | 9117 | Symbol &ultimate{name.symbol->GetUltimate()};
|
9110 | 9118 | if (!context().HasError(ultimate)) {
|
9111 |
| - if (IsPointer(ultimate)) { |
| 9119 | + if (IsPointer(ultimate) && !inLegacyDataInitialization) { |
9112 | 9120 | Say(name,
|
9113 | 9121 | "'%s' is a pointer but is not initialized like one"_err_en_US);
|
9114 | 9122 | } else if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {
|
9115 | 9123 | if (details->init()) {
|
9116 | 9124 | SayWithDecl(name, *name.symbol,
|
9117 | 9125 | "'%s' has already been initialized"_err_en_US);
|
9118 |
| - } else if (details->isCDefined()) { |
9119 |
| - context().Warn(common::UsageWarning::CdefinedInit, name.source, |
9120 |
| - "CDEFINED variable should not have an initializer"_warn_en_US); |
9121 | 9126 | } else if (IsAllocatable(ultimate)) {
|
9122 | 9127 | Say(name, "Allocatable object '%s' cannot be initialized"_err_en_US);
|
9123 |
| - } else if (ultimate.owner().IsParameterizedDerivedType()) { |
9124 |
| - // Save the expression for per-instantiation analysis. |
9125 |
| - details->set_unanalyzedPDTComponentInit(&expr.thing.value()); |
9126 |
| - } else if (MaybeExpr folded{EvaluateNonPointerInitializer( |
9127 |
| - ultimate, expr, expr.thing.value().source)}) { |
9128 |
| - details->set_init(std::move(*folded)); |
9129 |
| - ultimate.set(Symbol::Flag::InDataStmt, false); |
| 9128 | + } else { |
| 9129 | + if (details->isCDefined()) { |
| 9130 | + context().Warn(common::UsageWarning::CdefinedInit, name.source, |
| 9131 | + "CDEFINED variable should not have an initializer"_warn_en_US); |
| 9132 | + } |
| 9133 | + return true; |
9130 | 9134 | }
|
9131 | 9135 | } else {
|
9132 | 9136 | Say(name, "'%s' is not an object that can be initialized"_err_en_US);
|
9133 | 9137 | }
|
9134 | 9138 | }
|
9135 | 9139 | }
|
| 9140 | + return false; |
| 9141 | +} |
| 9142 | + |
| 9143 | +void DeclarationVisitor::NonPointerInitialization( |
| 9144 | + const parser::Name &name, const parser::ConstantExpr &expr) { |
| 9145 | + if (CheckNonPointerInitialization( |
| 9146 | + name, /*inLegacyDataInitialization=*/false)) { |
| 9147 | + Symbol &ultimate{name.symbol->GetUltimate()}; |
| 9148 | + auto &details{ultimate.get<ObjectEntityDetails>()}; |
| 9149 | + if (ultimate.owner().IsParameterizedDerivedType()) { |
| 9150 | + // Save the expression for per-instantiation analysis. |
| 9151 | + details.set_unanalyzedPDTComponentInit(&expr.thing.value()); |
| 9152 | + } else if (MaybeExpr folded{EvaluateNonPointerInitializer( |
| 9153 | + ultimate, expr, expr.thing.value().source)}) { |
| 9154 | + details.set_init(std::move(*folded)); |
| 9155 | + ultimate.set(Symbol::Flag::InDataStmt, false); |
| 9156 | + } |
| 9157 | + } |
| 9158 | +} |
| 9159 | + |
| 9160 | +void DeclarationVisitor::LegacyDataInitialization(const parser::Name &name, |
| 9161 | + const std::list<common::Indirection<parser::DataStmtValue>> &values) { |
| 9162 | + if (CheckNonPointerInitialization( |
| 9163 | + name, /*inLegacyDataInitialization=*/true)) { |
| 9164 | + Symbol &ultimate{name.symbol->GetUltimate()}; |
| 9165 | + if (ultimate.owner().IsParameterizedDerivedType()) { |
| 9166 | + Say(name, |
| 9167 | + "Component '%s' in a parameterized data type may not be initialized with a legacy DATA-style value list"_err_en_US, |
| 9168 | + name.source); |
| 9169 | + } else { |
| 9170 | + evaluate::ExpressionAnalyzer exprAnalyzer{context()}; |
| 9171 | + for (const auto &value : values) { |
| 9172 | + exprAnalyzer.Analyze(value.value()); |
| 9173 | + } |
| 9174 | + DataInitializations inits; |
| 9175 | + auto oldSize{ultimate.size()}; |
| 9176 | + if (auto chars{evaluate::characteristics::TypeAndShape::Characterize( |
| 9177 | + ultimate, GetFoldingContext())}) { |
| 9178 | + if (auto size{evaluate::ToInt64( |
| 9179 | + chars->MeasureSizeInBytes(GetFoldingContext()))}) { |
| 9180 | + // Temporarily set the byte size of the component so that we don't |
| 9181 | + // get bogus "initialization out of range" errors below. |
| 9182 | + ultimate.set_size(*size); |
| 9183 | + } |
| 9184 | + } |
| 9185 | + AccumulateDataInitializations(inits, exprAnalyzer, ultimate, values); |
| 9186 | + ConvertToInitializers(inits, exprAnalyzer); |
| 9187 | + ultimate.set_size(oldSize); |
| 9188 | + } |
| 9189 | + } |
9136 | 9190 | }
|
9137 | 9191 |
|
9138 | 9192 | void ResolveNamesVisitor::HandleCall(
|
@@ -10482,12 +10536,16 @@ class DeferredCheckVisitor {
|
10482 | 10536 | if (const auto *target{
|
10483 | 10537 | std::get_if<parser::InitialDataTarget>(&init->u)}) {
|
10484 | 10538 | resolver_.PointerInitialization(name, *target);
|
10485 |
| - } else if (const auto *expr{ |
10486 |
| - std::get_if<parser::ConstantExpr>(&init->u)}) { |
10487 |
| - if (name.symbol) { |
10488 |
| - if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()}; |
10489 |
| - !object || !object->init()) { |
| 10539 | + } else if (name.symbol) { |
| 10540 | + if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()}; |
| 10541 | + !object || !object->init()) { |
| 10542 | + if (const auto *expr{std::get_if<parser::ConstantExpr>(&init->u)}) { |
10490 | 10543 | resolver_.NonPointerInitialization(name, *expr);
|
| 10544 | + } else { |
| 10545 | + // Don't check legacy DATA /initialization/ here. Component |
| 10546 | + // initializations will have already been handled, and variable |
| 10547 | + // initializations need to be done in DATA checking so that |
| 10548 | + // EQUIVALENCE storage association can be handled. |
10491 | 10549 | }
|
10492 | 10550 | }
|
10493 | 10551 | }
|
|
0 commit comments