Skip to content

Commit

Permalink
[flang] Create symbols for args of separate-module-subprogram
Browse files Browse the repository at this point in the history
A separate-module-subprogram is declared as `module procedure ...`
and gets its characteristics from the declaration of that name as
a separate module procedure. When we encounter one, we need to create
symbols in the new subprogram scope for the dummy arguments and
function return (if any).

The failure to create these symbols led to the bug in issue flang-compiler/f18#1054:
when a dummy argument was referenced, the compiler interpreted it as
an implicit declaration because there was no symbol for the argument.

Fixes flang-compiler/f18#1054.

Original-commit: flang-compiler/f18@4d3c4ba
Reviewed-on: flang-compiler/f18#1080
Tree-same-pre-rewrite: false
  • Loading branch information
tskeith committed Mar 17, 2020
1 parent d1ce4d2 commit 824d198
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
2 changes: 2 additions & 0 deletions flang/include/flang/Semantics/scope.h
Expand Up @@ -134,6 +134,8 @@ class Scope {
Symbol &symbol{MakeSymbol(name, attrs, std::move(details))};
return symbols_.emplace(name, symbol);
}
// Make a copy of a symbol in this scope; nullptr if one is already there
Symbol *CopySymbol(const Symbol &);

const std::list<EquivalenceSet> &equivalenceSets() const;
void add_equivalenceSet(EquivalenceSet &&);
Expand Down
21 changes: 18 additions & 3 deletions flang/lib/Semantics/resolve-names.cpp
Expand Up @@ -2729,10 +2729,25 @@ bool SubprogramVisitor::BeginMpSubprogram(const parser::Name &name) {
Say(name, "'%s' was not declared a separate module procedure"_err_en_US);
return false;
}
if (symbol->owner() != currScope()) {
symbol = &MakeSymbol(name, SubprogramDetails{});
if (symbol->owner() == currScope()) {
PushScope(Scope::Kind::Subprogram, symbol);
} else {
Symbol &newSymbol{MakeSymbol(name, SubprogramDetails{})};
PushScope(Scope::Kind::Subprogram, &newSymbol);
const auto &details{symbol->get<SubprogramDetails>()};
auto &newDetails{newSymbol.get<SubprogramDetails>()};
for (const Symbol *dummyArg : details.dummyArgs()) {
if (!dummyArg) {
newDetails.add_alternateReturn();
} else if (Symbol * copy{currScope().CopySymbol(*dummyArg)}) {
newDetails.add_dummyArg(*copy);
}
}
if (details.isFunction()) {
currScope().erase(symbol->name());
newDetails.set_result(*currScope().CopySymbol(details.result()));
}
}
PushScope(Scope::Kind::Subprogram, symbol);
return true;
}

Expand Down
12 changes: 12 additions & 0 deletions flang/lib/Semantics/scope.cpp
Expand Up @@ -110,6 +110,18 @@ bool Scope::Contains(const Scope &that) const {
}
}

Symbol *Scope::CopySymbol(const Symbol &symbol) {
auto pair{try_emplace(symbol.name(), symbol.attrs())};
if (!pair.second) {
return nullptr; // already exists
} else {
Symbol &result{*pair.first->second};
result.flags() = symbol.flags();
result.set_details(common::Clone(symbol.details()));
return &result;
}
}

const std::list<EquivalenceSet> &Scope::equivalenceSets() const {
return equivalenceSets_;
}
Expand Down
30 changes: 30 additions & 0 deletions flang/test/Semantics/resolve76.f90
@@ -0,0 +1,30 @@
! RUN: %S/test_errors.sh %s %flang %t

! 15.6.2.5(3)

module m1
implicit logical(a-b)
interface
module subroutine sub1(a, b)
real, intent(in) :: a
real, intent(out) :: b
end
logical module function f()
end
end interface
end
submodule(m1) sm1
contains
module procedure sub1
!ERROR: Left-hand side of assignment is not modifiable
a = 1.0
b = 2.0
!ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types REAL(4) and LOGICAL(4)
b = .false.
end
module procedure f
f = .true.
!ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types LOGICAL(4) and REAL(4)
f = 1.0
end
end

0 comments on commit 824d198

Please sign in to comment.