Other Fortran compilers disagree in their interpretations of this example;
some seem to treat the references to `m` as if they were host associations
to an implicitly typed variable (and print `3`), while others seem to
- treat them as references to implicitly typed local variabless, and
+ treat them as references to implicitly typed local variables, and
load uninitialized values.
In f18, we chose to emit an error message for this case since the standard
const Scope *ancestor() const; // for submodule; nullptr for module
const Scope *parent() const; // for submodule; nullptr for module
void set_scope(const Scope *);
+ bool isDefaultPrivate() const { return isDefaultPrivate_; }
+ void set_isDefaultPrivate(bool yes = true) { isDefaultPrivate_ = yes; }
private:
bool isSubmodule_;
+ bool isDefaultPrivate_{false};
const Scope *scope_{nullptr};
};
}
private:
- // The default access spec for this module.
- Attr defaultAccess_{Attr::PUBLIC};
// The location of the last AccessStmt without access-ids, if any.
std::optional<SourceName> prevAccessStmt_;
// The scope of the module during a UseStmt
auto &details{symbol.get<ModuleDetails>()};
PushScope(Scope::Kind::Module, &symbol);
details.set_scope(&currScope());
- defaultAccess_ = Attr::PUBLIC;
prevAccessStmt_ = std::nullopt;
}
}
void ModuleVisitor::ApplyDefaultAccess() {
+ const auto *moduleDetails{
+ DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};
+ CHECK(moduleDetails);
for (auto &pair : currScope()) {
- Symbol &symbol = *pair.second;
+ Symbol &symbol{*pair.second};
if (!symbol.attrs().HasAny({Attr::PUBLIC, Attr::PRIVATE})) {
- SetImplicitAttr(symbol, defaultAccess_);
+ SetImplicitAttr(symbol,
+ DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE
+ : Attr::PUBLIC);
}
}
}
.Attach(*prevAccessStmt_, "Previous declaration"_en_US);
}
prevAccessStmt_ = currStmtSource();
- defaultAccess_ = accessAttr;
+ auto *moduleDetails{DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};
+ DEREF(moduleDetails).set_isDefaultPrivate(accessAttr == Attr::PRIVATE);
} else {
for (const auto &accessId : accessIds) {
GenericSpecInfo info{accessId.v.value()};
Walk(*exec);
}
FinishNamelists();
+ if (node.IsModule()) {
+ // A second final pass to catch new symbols added from implicitly
+ // typed names in NAMELIST groups or the specification parts of
+ // module subprograms.
+ ApplyDefaultAccess();
+ }
PopScope(); // converts unclassified entities into objects
for (const auto &child : node.children()) {
ResolveExecutionParts(child);
--- /dev/null
+! RUN: %python %S/test_symbols.py %s %flang_fc1
+! Regression test for https://github.com/llvm/llvm-project/issues/62598
+! Ensure that implicitly typed names in module NAMELIST groups receive
+! the module's default accessibility attribute.
+!DEF: /m Module
+module m
+ !DEF: /m/a PUBLIC Namelist
+ !DEF: /m/j PUBLIC (Implicit, InNamelist) ObjectEntity INTEGER(4)
+ namelist/a/j
+end module m
+!DEF: /main MainProgram
+program main
+ !DEF: /main/j (Implicit) ObjectEntity INTEGER(4)
+ j = 1
+contains
+ !DEF: /main/inner (Subroutine) Subprogram
+ subroutine inner
+ !REF: /m
+ use :: m
+ !DEF: /main/inner/j (Implicit, InNamelist) Use INTEGER(4)
+ j = 2
+ end subroutine
+end program