@@ -2548,9 +2548,11 @@ void ScopeHandler::PopScope() {
2548
2548
ConvertToObjectEntity (*pair.second );
2549
2549
}
2550
2550
funcResultStack_.Pop ();
2551
- // If popping back into a global scope, pop back to the main global scope.
2552
- SetScope (currScope_->parent ().IsGlobal () ? context ().globalScope ()
2553
- : currScope_->parent ());
2551
+ // If popping back into a global scope, pop back to the top scope.
2552
+ Scope *hermetic{context ().currentHermeticModuleFileScope ()};
2553
+ SetScope (currScope_->parent ().IsGlobal ()
2554
+ ? (hermetic ? *hermetic : context ().globalScope ())
2555
+ : currScope_->parent ());
2554
2556
}
2555
2557
void ScopeHandler::SetScope (Scope &scope) {
2556
2558
currScope_ = &scope;
@@ -3179,6 +3181,111 @@ static bool ConvertToUseError(
3179
3181
}
3180
3182
}
3181
3183
3184
+ // Two ultimate symbols are distinct, but they have the same name and come
3185
+ // from modules with the same name. At link time, their mangled names
3186
+ // would conflict, so they had better resolve to the same definition.
3187
+ // Check whether the two ultimate symbols have compatible definitions.
3188
+ // Returns true if no further processing is required in DoAddUse().
3189
+ static bool CheckCompatibleDistinctUltimates (SemanticsContext &context,
3190
+ SourceName location, SourceName localName, const Symbol &localSymbol,
3191
+ const Symbol &localUltimate, const Symbol &useUltimate) {
3192
+ bool bad{false };
3193
+ if (localUltimate.has <GenericDetails>()) {
3194
+ if (useUltimate.has <GenericDetails>() ||
3195
+ useUltimate.has <SubprogramDetails>() ||
3196
+ useUltimate.has <DerivedTypeDetails>()) {
3197
+ return false ; // can try to merge them
3198
+ } else {
3199
+ bad = true ;
3200
+ }
3201
+ } else if (useUltimate.has <GenericDetails>()) {
3202
+ if (localUltimate.has <SubprogramDetails>() ||
3203
+ localUltimate.has <DerivedTypeDetails>()) {
3204
+ return false ; // can try to merge them
3205
+ } else {
3206
+ bad = true ;
3207
+ }
3208
+ } else if (localUltimate.has <SubprogramDetails>()) {
3209
+ if (useUltimate.has <SubprogramDetails>()) {
3210
+ auto localCharacteristics{
3211
+ evaluate::characteristics::Procedure::Characterize (
3212
+ localUltimate, context.foldingContext ())};
3213
+ auto useCharacteristics{
3214
+ evaluate::characteristics::Procedure::Characterize (
3215
+ useUltimate, context.foldingContext ())};
3216
+ if ((localCharacteristics &&
3217
+ (!useCharacteristics ||
3218
+ *localCharacteristics != *useCharacteristics)) ||
3219
+ (!localCharacteristics && useCharacteristics)) {
3220
+ bad = true ;
3221
+ }
3222
+ } else {
3223
+ bad = true ;
3224
+ }
3225
+ } else if (useUltimate.has <SubprogramDetails>()) {
3226
+ bad = true ;
3227
+ } else if (const auto *localObject{
3228
+ localUltimate.detailsIf <ObjectEntityDetails>()}) {
3229
+ if (const auto *useObject{useUltimate.detailsIf <ObjectEntityDetails>()}) {
3230
+ auto localType{evaluate::DynamicType::From (localUltimate)};
3231
+ auto useType{evaluate::DynamicType::From (useUltimate)};
3232
+ if (localUltimate.size () != useUltimate.size () ||
3233
+ (localType &&
3234
+ (!useType || !localType->IsTkLenCompatibleWith (*useType) ||
3235
+ !useType->IsTkLenCompatibleWith (*localType))) ||
3236
+ (!localType && useType)) {
3237
+ bad = true ;
3238
+ } else if (IsNamedConstant (localUltimate)) {
3239
+ bad = !IsNamedConstant (useUltimate) ||
3240
+ !(*localObject->init () == *useObject->init ());
3241
+ } else {
3242
+ bad = IsNamedConstant (useUltimate);
3243
+ }
3244
+ } else {
3245
+ bad = true ;
3246
+ }
3247
+ } else if (useUltimate.has <ObjectEntityDetails>()) {
3248
+ bad = true ;
3249
+ } else if (IsProcedurePointer (localUltimate)) {
3250
+ bad = !IsProcedurePointer (useUltimate);
3251
+ } else if (IsProcedurePointer (useUltimate)) {
3252
+ bad = true ;
3253
+ } else if (localUltimate.has <DerivedTypeDetails>()) {
3254
+ bad = !(useUltimate.has <DerivedTypeDetails>() &&
3255
+ evaluate::AreSameDerivedTypeIgnoringSequence (
3256
+ DerivedTypeSpec{localUltimate.name (), localUltimate},
3257
+ DerivedTypeSpec{useUltimate.name (), useUltimate}));
3258
+ } else if (useUltimate.has <DerivedTypeDetails>()) {
3259
+ bad = true ;
3260
+ } else if (localUltimate.has <NamelistDetails>() &&
3261
+ useUltimate.has <NamelistDetails>()) {
3262
+ } else if (localUltimate.has <CommonBlockDetails>() &&
3263
+ useUltimate.has <CommonBlockDetails>()) {
3264
+ } else {
3265
+ bad = true ;
3266
+ }
3267
+ if (bad) {
3268
+ context
3269
+ .Say (location,
3270
+ " '%s' use-associated from '%s' in module '%s' is incompatible with '%s' from another module" _err_en_US,
3271
+ localName, useUltimate.name (),
3272
+ useUltimate.owner ().GetName ().value (), localUltimate.name ())
3273
+ .Attach (useUltimate.name (), " First declaration" _en_US)
3274
+ .Attach (localUltimate.name (), " Other declaration" _en_US);
3275
+ return true ;
3276
+ }
3277
+ if (auto *msg{context.Warn (
3278
+ common::UsageWarning::CompatibleDeclarationsFromDistinctModules,
3279
+ location,
3280
+ " '%s' is use-associated from '%s' in two distinct instances of module '%s'" _warn_en_US,
3281
+ localName, localUltimate.name (),
3282
+ localUltimate.owner ().GetName ().value ())}) {
3283
+ msg->Attach (localUltimate.name (), " Previous declaration" _en_US)
3284
+ .Attach (useUltimate.name (), " Later declaration" _en_US);
3285
+ }
3286
+ return true ;
3287
+ }
3288
+
3182
3289
void ModuleVisitor::DoAddUse (SourceName location, SourceName localName,
3183
3290
Symbol &originalLocal, const Symbol &useSymbol) {
3184
3291
Symbol *localSymbol{&originalLocal};
@@ -3220,6 +3327,16 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
3220
3327
return ;
3221
3328
}
3222
3329
3330
+ if (localUltimate.name () == useUltimate.name () &&
3331
+ localUltimate.owner ().IsModule () && useUltimate.owner ().IsModule () &&
3332
+ localUltimate.owner ().GetName () &&
3333
+ localUltimate.owner ().GetName () == useUltimate.owner ().GetName ()) {
3334
+ if (CheckCompatibleDistinctUltimates (context (), location, localName,
3335
+ *localSymbol, localUltimate, useUltimate)) {
3336
+ return ;
3337
+ }
3338
+ }
3339
+
3223
3340
// There are many possible combinations of symbol types that could arrive
3224
3341
// with the same (local) name vie USE association from distinct modules.
3225
3342
// Fortran allows a generic interface to share its name with a derived type,
@@ -9375,6 +9492,12 @@ template <typename A> std::set<SourceName> GetUses(const A &x) {
9375
9492
}
9376
9493
9377
9494
bool ResolveNamesVisitor::Pre (const parser::Program &x) {
9495
+ if (Scope * hermetic{context ().currentHermeticModuleFileScope ()}) {
9496
+ // Processing either the dependent modules or first module of a
9497
+ // hermetic module file; ensure that the hermetic module scope has
9498
+ // its implicit rules map entry.
9499
+ ImplicitRulesVisitor::BeginScope (*hermetic);
9500
+ }
9378
9501
std::map<SourceName, const parser::ProgramUnit *> modules;
9379
9502
std::set<SourceName> uses;
9380
9503
bool disordered{false };
0 commit comments