This is an archive of the discontinued LLVM Phabricator instance.

[flang] Fix bug accessing implicit variable in specification expression
ClosedPublic

Authored by tskeith on Aug 20 2020, 4:37 PM.

Details

Summary

A specification expression can reference an implicitly declared variable
in the host procedure. Because we have to process specification parts
before execution parts, this may be the first time we encounter the
variable. We were assuming the variable was implicitly declared in the
scope where it was encountered, leading to an error because local
variables may not be referenced in specification expressions.

The fix is to tentatively create the implicit variable in the host
procedure because that is the only way the specification expression can
be valid. We mark it with the flag ImplicitOrError to indicate that
either it must be implicitly defined in the host (by being mentioned in
the execution part) or else its use turned out to be an error.
We need to apply the implicit type rules of the host, which requires
some changes to implicit typing.

Variables in common blocks are allowed to appear in specification expressions
(because they are not locals) but the common block definition may not appear
until after their use. To handle this we create common block symbols and object
entities for each common block object during the PreSpecificationConstruct
pass. This allows us to remove the corresponding code in the main visitor and
commonBlockInfo_.curr. The change in order of processing causes some
different error messages to be emitted.

Some cleanup is included with this change:

  • In ExpressionAnalyzer, if an unresolved name is encountered but no error has been reported, emit an internal error.
  • Change ImplicitRulesVisitor to hide the ImplicitRules object that implements it. Change the interface to pass in names rather than having to get the first character of the name.
  • Change DeclareObjectEntity to have the attrs argument default to an empty set; that is the typical case.
  • In Pre(parser::SpecificationPart) use "structured bindings" to give names to the pieces that make up a specification-part.
  • Enhance parser::Unwrap to unwrap Statement and UnlabeledStatement and make use of that in PreSpecificationConstruct.

Diff Detail

Event Timeline

tskeith created this revision.Aug 20 2020, 4:37 PM
Herald added a project: Restricted Project. · View Herald Transcript
tskeith requested review of this revision.Aug 20 2020, 4:37 PM
PeteSteinfeld accepted this revision.Aug 20 2020, 8:01 PM

All builds, tests, and looks good.

This revision is now accepted and ready to land.Aug 20 2020, 8:01 PM
klausler accepted this revision.Aug 21 2020, 9:47 AM
klausler added inline comments.
flang/include/flang/Semantics/symbol.h
486

"implicitly typed"

flang/lib/Semantics/check-declarations.cpp
770

"implicitly typed" might be better here too.

flang/lib/Semantics/resolve-names.cpp
1938

Consider adding a "while" predicate to this loop. It'll never be false, but it would remove the need for the reader to have to think about it.

5475

Can some of this logic be simplified if the internal procedure or the host has IMPLICIT NONE? Or maybe I'm missing out on how it works. But it seems like we need these new features only when neither scope has IMPLICIT NONE.

5999

Instead of using a new flag here, you could declare the common block's symbol and point the block's objects to it.

flang/test/Semantics/block-data01.f90
10–12

Is the old error message now dead? Maybe there's useless code that can be cleaned out from check-declarations.cpp.

flang/test/Semantics/implicit11.f90
53

Consider adding a test case with IMPLICIT NONE in the host procedure.

tskeith updated this revision to Diff 287150.Aug 21 2020, 7:31 PM

Address review comments

Create common block symbol in PreSpecificationConstruct so that common
block objects can immediately be added to them. Remove the corresponding
code in the main visitor and commonBlockInfo_.curr. Eliminate the
InCommonBlock flag because the InCommonBlock function can replace it.
Move that function to tools.{h,cpp}.

Enhance parser::Unwrap to unwrap Statement and UnlabeledStatement and
make use of that in PreSpecificationConstruct.

tskeith updated this revision to Diff 287200.Aug 22 2020, 10:03 AM
tskeith marked 5 inline comments as done.
  • Handle IMPLICIT NONE in host procedure
tskeith edited the summary of this revision. (Show Details)Aug 22 2020, 10:10 AM
tskeith marked an inline comment as done.
tskeith added inline comments.
flang/lib/Semantics/resolve-names.cpp
5475

If the internal procedure has IMPLICIT NONE but the host does not, we still need this. That's why we don't get an error on m in subroutine s1a in implicit11.f90.

I've changed this function to exit early when the host has IMPLICIT NONE.

5999

Yes, that's a better way to do it. Now it's all done in CreateCommonBlockSymbols and that allows the main visitor to be simplified.

flang/test/Semantics/block-data01.f90
10–12

It can still happen. I've added a new test that produces it.

flang/test/Semantics/implicit11.f90
53

Thanks -- I did that and it turned up another small change that was needed.

LGTM & thanks!

This revision was automatically updated to reflect the committed changes.
tskeith marked an inline comment as done.