@@ -69,7 +69,8 @@ class ImplicitRules {
69
69
void set_isImplicitNoneExternal (bool x) { isImplicitNoneExternal_ = x; }
70
70
void set_inheritFromParent (bool x) { inheritFromParent_ = x; }
71
71
// Get the implicit type for this name. May be null.
72
- const DeclTypeSpec *GetType (SourceName) const ;
72
+ const DeclTypeSpec *GetType (
73
+ SourceName, bool respectImplicitNone = true ) const ;
73
74
// Record the implicit type for the range of characters [fromLetter,
74
75
// toLetter].
75
76
void SetTypeMapping (const DeclTypeSpec &type, parser::Location fromLetter,
@@ -380,8 +381,9 @@ class ImplicitRulesVisitor : public DeclTypeSpecVisitor {
380
381
bool Pre (const parser::ImplicitSpec &);
381
382
void Post (const parser::ImplicitSpec &);
382
383
383
- const DeclTypeSpec *GetType (SourceName name) {
384
- return implicitRules_->GetType (name);
384
+ const DeclTypeSpec *GetType (
385
+ SourceName name, bool respectImplicitNoneType = true ) {
386
+ return implicitRules_->GetType (name, respectImplicitNoneType);
385
387
}
386
388
bool isImplicitNoneType () const {
387
389
return implicitRules_->isImplicitNoneType ();
@@ -583,9 +585,11 @@ class ScopeHandler : public ImplicitRulesVisitor {
583
585
584
586
protected:
585
587
// Apply the implicit type rules to this symbol.
586
- void ApplyImplicitRules (Symbol &);
588
+ void ApplyImplicitRules (Symbol &, bool allowForwardReference = false );
589
+ bool ImplicitlyTypeForwardRef (Symbol &);
587
590
void AcquireIntrinsicProcedureFlags (Symbol &);
588
- const DeclTypeSpec *GetImplicitType (Symbol &, const Scope &);
591
+ const DeclTypeSpec *GetImplicitType (
592
+ Symbol &, bool respectImplicitNoneType = true );
589
593
bool ConvertToObjectEntity (Symbol &);
590
594
bool ConvertToProcEntity (Symbol &);
591
595
@@ -1412,14 +1416,15 @@ bool ImplicitRules::isImplicitNoneExternal() const {
1412
1416
}
1413
1417
}
1414
1418
1415
- const DeclTypeSpec *ImplicitRules::GetType (SourceName name) const {
1419
+ const DeclTypeSpec *ImplicitRules::GetType (
1420
+ SourceName name, bool respectImplicitNoneType) const {
1416
1421
char ch{name.begin ()[0 ]};
1417
- if (isImplicitNoneType_) {
1422
+ if (isImplicitNoneType_ && respectImplicitNoneType ) {
1418
1423
return nullptr ;
1419
1424
} else if (auto it{map_.find (ch)}; it != map_.end ()) {
1420
1425
return &*it->second ;
1421
1426
} else if (inheritFromParent_) {
1422
- return parent_->GetType (name);
1427
+ return parent_->GetType (name, respectImplicitNoneType );
1423
1428
} else if (ch >= ' i' && ch <= ' n' ) {
1424
1429
return &context_.MakeNumericType (TypeCategory::Integer);
1425
1430
} else if (ch >= ' a' && ch <= ' z' ) {
@@ -2125,39 +2130,72 @@ static bool NeedsType(const Symbol &symbol) {
2125
2130
symbol.details ());
2126
2131
}
2127
2132
2128
- void ScopeHandler::ApplyImplicitRules (Symbol &symbol) {
2129
- if (NeedsType (symbol)) {
2130
- const Scope *scope{&symbol.owner ()};
2131
- if (scope->IsGlobal ()) {
2132
- scope = &currScope ();
2133
+ void ScopeHandler::ApplyImplicitRules (
2134
+ Symbol &symbol, bool allowForwardReference) {
2135
+ if (!NeedsType (symbol)) {
2136
+ return ;
2137
+ }
2138
+ if (const DeclTypeSpec * type{GetImplicitType (symbol)}) {
2139
+ symbol.set (Symbol::Flag::Implicit);
2140
+ symbol.SetType (*type);
2141
+ return ;
2142
+ }
2143
+ if (symbol.has <ProcEntityDetails>() && !symbol.attrs ().test (Attr::EXTERNAL)) {
2144
+ std::optional<Symbol::Flag> functionOrSubroutineFlag;
2145
+ if (symbol.test (Symbol::Flag::Function)) {
2146
+ functionOrSubroutineFlag = Symbol::Flag::Function;
2147
+ } else if (symbol.test (Symbol::Flag::Subroutine)) {
2148
+ functionOrSubroutineFlag = Symbol::Flag::Subroutine;
2133
2149
}
2134
- if (const DeclTypeSpec *
2135
- type{GetImplicitType (symbol, GetInclusiveScope (*scope))}) {
2136
- symbol.set (Symbol::Flag::Implicit);
2137
- symbol.SetType (*type);
2150
+ if (IsIntrinsic (symbol.name (), functionOrSubroutineFlag)) {
2151
+ // type will be determined in expression semantics
2152
+ AcquireIntrinsicProcedureFlags (symbol);
2138
2153
return ;
2139
2154
}
2140
- if (symbol.has <ProcEntityDetails>() &&
2141
- !symbol.attrs ().test (Attr::EXTERNAL)) {
2142
- std::optional<Symbol::Flag> functionOrSubroutineFlag;
2143
- if (symbol.test (Symbol::Flag::Function)) {
2144
- functionOrSubroutineFlag = Symbol::Flag::Function;
2145
- } else if (symbol.test (Symbol::Flag::Subroutine)) {
2146
- functionOrSubroutineFlag = Symbol::Flag::Subroutine;
2147
- }
2148
- if (IsIntrinsic (symbol.name (), functionOrSubroutineFlag)) {
2149
- // type will be determined in expression semantics
2150
- AcquireIntrinsicProcedureFlags (symbol);
2151
- return ;
2152
- }
2153
- }
2154
- if (!context ().HasError (symbol)) {
2155
- Say (symbol.name (), " No explicit type declared for '%s'" _err_en_US);
2156
- context ().SetError (symbol);
2157
- }
2155
+ }
2156
+ if (allowForwardReference && ImplicitlyTypeForwardRef (symbol)) {
2157
+ return ;
2158
+ }
2159
+ if (!context ().HasError (symbol)) {
2160
+ Say (symbol.name (), " No explicit type declared for '%s'" _err_en_US);
2161
+ context ().SetError (symbol);
2158
2162
}
2159
2163
}
2160
2164
2165
+ // Extension: Allow forward references to scalar integer dummy arguments
2166
+ // to appear in specification expressions under IMPLICIT NONE(TYPE) when
2167
+ // what would otherwise have been their implicit type is default INTEGER.
2168
+ bool ScopeHandler::ImplicitlyTypeForwardRef (Symbol &symbol) {
2169
+ if (!inSpecificationPart_ || context ().HasError (symbol) || !IsDummy (symbol) ||
2170
+ symbol.Rank () != 0 ||
2171
+ !context ().languageFeatures ().IsEnabled (
2172
+ common::LanguageFeature::ForwardRefDummyImplicitNone)) {
2173
+ return false ;
2174
+ }
2175
+ const DeclTypeSpec *type{
2176
+ GetImplicitType (symbol, false /* ignore IMPLICIT NONE*/ )};
2177
+ if (!type || !type->IsNumeric (TypeCategory::Integer)) {
2178
+ return false ;
2179
+ }
2180
+ auto kind{evaluate::ToInt64 (type->numericTypeSpec ().kind ())};
2181
+ if (!kind || *kind != context ().GetDefaultKind (TypeCategory::Integer)) {
2182
+ return false ;
2183
+ }
2184
+ if (!ConvertToObjectEntity (symbol)) {
2185
+ return false ;
2186
+ }
2187
+ // TODO: check no INTENT(OUT)?
2188
+ if (context ().languageFeatures ().ShouldWarn (
2189
+ common::LanguageFeature::ForwardRefDummyImplicitNone)) {
2190
+ Say (symbol.name (),
2191
+ " Dummy argument '%s' was used without being explicitly typed" _en_US,
2192
+ symbol.name ());
2193
+ }
2194
+ symbol.set (Symbol::Flag::Implicit);
2195
+ symbol.SetType (*type);
2196
+ return true ;
2197
+ }
2198
+
2161
2199
// Ensure that the symbol for an intrinsic procedure is marked with
2162
2200
// the INTRINSIC attribute. Also set PURE &/or ELEMENTAL as
2163
2201
// appropriate.
@@ -2177,8 +2215,14 @@ void ScopeHandler::AcquireIntrinsicProcedureFlags(Symbol &symbol) {
2177
2215
}
2178
2216
2179
2217
const DeclTypeSpec *ScopeHandler::GetImplicitType (
2180
- Symbol &symbol, const Scope &scope) {
2181
- const auto *type{implicitRulesMap_->at (&scope).GetType (symbol.name ())};
2218
+ Symbol &symbol, bool respectImplicitNoneType) {
2219
+ const Scope *scope{&symbol.owner ()};
2220
+ if (scope->IsGlobal ()) {
2221
+ scope = &currScope ();
2222
+ }
2223
+ scope = &GetInclusiveScope (*scope);
2224
+ const auto *type{implicitRulesMap_->at (scope).GetType (
2225
+ symbol.name (), respectImplicitNoneType)};
2182
2226
if (type) {
2183
2227
if (const DerivedTypeSpec * derived{type->AsDerived ()}) {
2184
2228
// Resolve any forward-referenced derived type; a quick no-op else.
@@ -2282,6 +2326,16 @@ bool ScopeHandler::CheckPossibleBadForwardRef(const Symbol &symbol) {
2282
2326
context ().SetError (symbol);
2283
2327
return true ;
2284
2328
}
2329
+ if (IsDummy (symbol) && isImplicitNoneType () &&
2330
+ symbol.test (Symbol::Flag::Implicit) && !context ().HasError (symbol)) {
2331
+ // Dummy was implicitly typed despite IMPLICIT NONE(TYPE) in
2332
+ // ApplyImplicitRules() due to use in a specification expression,
2333
+ // and no explicit type declaration appeared later.
2334
+ Say (symbol.name (),
2335
+ " No explicit type declared for dummy argument '%s'" _err_en_US);
2336
+ context ().SetError (symbol);
2337
+ return true ;
2338
+ }
2285
2339
}
2286
2340
return false ;
2287
2341
}
@@ -5731,7 +5785,7 @@ bool DeclarationVisitor::CheckForHostAssociatedImplicit(
5731
5785
return false ;
5732
5786
}
5733
5787
if (name.symbol ) {
5734
- ApplyImplicitRules (*name.symbol );
5788
+ ApplyImplicitRules (*name.symbol , true );
5735
5789
}
5736
5790
Symbol *hostSymbol;
5737
5791
Scope *host{GetHostProcedure ()};
@@ -6282,6 +6336,12 @@ void ResolveNamesVisitor::FinishSpecificationPart(
6282
6336
if (NeedsExplicitType (symbol)) {
6283
6337
ApplyImplicitRules (symbol);
6284
6338
}
6339
+ if (IsDummy (symbol) && isImplicitNoneType () &&
6340
+ symbol.test (Symbol::Flag::Implicit) && !context ().HasError (symbol)) {
6341
+ Say (symbol.name (),
6342
+ " No explicit type declared for dummy argument '%s'" _err_en_US);
6343
+ context ().SetError (symbol);
6344
+ }
6285
6345
if (symbol.has <GenericDetails>()) {
6286
6346
CheckGenericProcedures (symbol);
6287
6347
}
0 commit comments