Skip to content

[flang] Fix spurious error with separate module procedures #106768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 4, 2024

Conversation

klausler
Copy link
Contributor

When the implementation of one SMP apparently references another in what might be a specification expression, semantics may need to resolve it as a forward reference, and to allow for the replacement of a SubprogramNameDetails place-holding symbol with the final SubprogramDetails symbol. Otherwise, as in the bug report below, confusing error messages may result.

(The reference in question isn't really in the specification part of a subprogram, but due to the syntactic ambiguity between the array element assignment statement and a statement function definition, it appears to be so at the time that the reference is processed.)

I needed to make DumpSymbols() available via SemanticsContext to analyze this bug, and left that new API in place to make things easier next time.

Fixes #106705.

When the implementation of one SMP apparently references another
in what might be a specification expression, semantics may need to
resolve it as a forward reference, and to allow for the replacement
of a SubprogramNameDetails place-holding symbol with the final
SubprogramDetails symbol.  Otherwise, as in the bug report below,
confusing error messages may result.

(The reference in question isn't really in the specification part
of a subprogram, but due to the syntactic ambiguity between the
array element assignment statement and a statement function definition,
it appears to be so at the time that the reference is processed.)

I needed to make DumpSymbols() available via SemanticsContext to
analyze this bug, and left that new API in place to make things
easier next time.

Fixes llvm#106705.
@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2024

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

When the implementation of one SMP apparently references another in what might be a specification expression, semantics may need to resolve it as a forward reference, and to allow for the replacement of a SubprogramNameDetails place-holding symbol with the final SubprogramDetails symbol. Otherwise, as in the bug report below, confusing error messages may result.

(The reference in question isn't really in the specification part of a subprogram, but due to the syntactic ambiguity between the array element assignment statement and a statement function definition, it appears to be so at the time that the reference is processed.)

I needed to make DumpSymbols() available via SemanticsContext to analyze this bug, and left that new API in place to make things easier next time.

Fixes #106705.


Full diff: https://github.com/llvm/llvm-project/pull/106768.diff

5 Files Affected:

  • (modified) flang/include/flang/Semantics/expression.h (+1-1)
  • (modified) flang/include/flang/Semantics/semantics.h (+2)
  • (modified) flang/lib/Semantics/expression.cpp (+26-15)
  • (modified) flang/lib/Semantics/semantics.cpp (+4-2)
  • (added) flang/test/Semantics/smp-proc-ref.f90 (+20)
diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index a224b08da21da7..b1304d704232dc 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -354,7 +354,7 @@ class ExpressionAnalyzer {
       parser::CharBlock, const ProcedureDesignator &, ActualArguments &);
   using AdjustActuals =
       std::optional<std::function<bool(const Symbol &, ActualArguments &)>>;
-  bool ResolveForward(const Symbol &);
+  const Symbol *ResolveForward(const Symbol &);
   std::pair<const Symbol *, bool /* failure due ambiguity */> ResolveGeneric(
       const Symbol &, const ActualArguments &, const AdjustActuals &,
       bool isSubroutine, bool mightBeStructureConstructor = false);
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index ec8d12b0f98653..e73f9d2e85d589 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -257,6 +257,8 @@ class SemanticsContext {
   void NoteDefinedSymbol(const Symbol &);
   bool IsSymbolDefined(const Symbol &) const;
 
+  void DumpSymbols(llvm::raw_ostream &);
+
 private:
   struct ScopeIndexComparator {
     bool operator()(parser::CharBlock, parser::CharBlock) const;
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 4f8632a2055d99..60db02dc764b46 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2650,9 +2650,9 @@ static int ComputeCudaMatchingDistance(
 // Handles a forward reference to a module function from what must
 // be a specification expression.  Return false if the symbol is
 // an invalid forward reference.
-bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
+const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
   if (context_.HasError(symbol)) {
-    return false;
+    return nullptr;
   }
   if (const auto *details{
           symbol.detailsIf<semantics::SubprogramNameDetails>()}) {
@@ -2661,8 +2661,13 @@ bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
       // checking a specification expression in a sibling module
       // procedure.  Resolve its names now so that its interface
       // is known.
+      const semantics::Scope &scope{symbol.owner()};
       semantics::ResolveSpecificationParts(context_, symbol);
-      if (symbol.has<semantics::SubprogramNameDetails>()) {
+      const Symbol *resolved{nullptr};
+      if (auto iter{scope.find(symbol.name())}; iter != scope.cend()) {
+        resolved = &*iter->second;
+      }
+      if (!resolved || resolved->has<semantics::SubprogramNameDetails>()) {
         // When the symbol hasn't had its details updated, we must have
         // already been in the process of resolving the function's
         // specification part; but recursive function calls are not
@@ -2670,8 +2675,8 @@ bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
         Say("The module function '%s' may not be referenced recursively in a specification expression"_err_en_US,
             symbol.name());
         context_.SetError(symbol);
-        return false;
       }
+      return resolved;
     } else if (inStmtFunctionDefinition_) {
       semantics::ResolveSpecificationParts(context_, symbol);
       CHECK(symbol.has<semantics::SubprogramDetails>());
@@ -2679,10 +2684,10 @@ bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
       Say("The internal function '%s' may not be referenced in a specification expression"_err_en_US,
           symbol.name());
       context_.SetError(symbol);
-      return false;
+      return nullptr;
     }
   }
-  return true;
+  return &symbol;
 }
 
 // Resolve a call to a generic procedure with given actual arguments.
@@ -2709,20 +2714,21 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
   }
   if (const auto *details{ultimate.detailsIf<semantics::GenericDetails>()}) {
     for (const Symbol &specific0 : details->specificProcs()) {
-      const Symbol &specific{BypassGeneric(specific0)};
-      if (isSubroutine != !IsFunction(specific)) {
+      const Symbol &specific1{BypassGeneric(specific0)};
+      if (isSubroutine != !IsFunction(specific1)) {
         continue;
       }
-      if (!ResolveForward(specific)) {
+      const Symbol *specific{ResolveForward(specific1)};
+      if (!specific) {
         continue;
       }
       if (std::optional<characteristics::Procedure> procedure{
               characteristics::Procedure::Characterize(
-                  ProcedureDesignator{specific}, context_.foldingContext(),
+                  ProcedureDesignator{*specific}, context_.foldingContext(),
                   /*emitError=*/false)}) {
         ActualArguments localActuals{actuals};
-        if (specific.has<semantics::ProcBindingDetails>()) {
-          if (!adjustActuals.value()(specific, localActuals)) {
+        if (specific->has<semantics::ProcBindingDetails>()) {
+          if (!adjustActuals.value()(*specific, localActuals)) {
             continue;
           }
         }
@@ -2751,9 +2757,9 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
           }
           if (!procedure->IsElemental()) {
             // takes priority over elemental match
-            nonElemental = &specific;
+            nonElemental = specific;
           } else {
-            elemental = &specific;
+            elemental = specific;
           }
           crtMatchingDistance = ComputeCudaMatchingDistance(
               context_.languageFeatures(), *procedure, localActuals);
@@ -2866,7 +2872,12 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
   if (context_.HasError(symbol)) {
     return std::nullopt; // also handles null symbol
   }
-  const Symbol &ultimate{DEREF(symbol).GetUltimate()};
+  symbol = ResolveForward(*symbol);
+  if (!symbol) {
+    return std::nullopt;
+  }
+  name.symbol = const_cast<Symbol *>(symbol);
+  const Symbol &ultimate{symbol->GetUltimate()};
   CheckForBadRecursion(name.source, ultimate);
   bool dueToAmbiguity{false};
   bool isGenericInterface{ultimate.has<semantics::GenericDetails>()};
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index f7a277d1b414f6..8592d1e5d6217e 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -655,10 +655,12 @@ void Semantics::EmitMessages(llvm::raw_ostream &os) {
   context_.messages().Emit(os, context_.allCookedSources());
 }
 
-void Semantics::DumpSymbols(llvm::raw_ostream &os) {
-  DoDumpSymbols(os, context_.globalScope());
+void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
+  DoDumpSymbols(os, globalScope());
 }
 
+void Semantics::DumpSymbols(llvm::raw_ostream &os) { context_.DumpSymbols(os); }
+
 void Semantics::DumpSymbolsSources(llvm::raw_ostream &os) const {
   NameToSymbolMap symbols;
   GetSymbolNames(context_.globalScope(), symbols);
diff --git a/flang/test/Semantics/smp-proc-ref.f90 b/flang/test/Semantics/smp-proc-ref.f90
new file mode 100644
index 00000000000000..9a2fae442e8e70
--- /dev/null
+++ b/flang/test/Semantics/smp-proc-ref.f90
@@ -0,0 +1,20 @@
+!RUN: %flang_fc1 -fsyntax-only %s
+module m
+  real :: qux(10)
+  interface
+    module subroutine bar(i)
+    end
+    module function baz()
+    end
+  end interface
+end
+
+submodule(m) sm
+ contains
+  module procedure bar
+    qux(i) = baz() ! ensure no bogus error here
+  end
+  module procedure baz
+    baz = 1.
+  end
+end

@klausler klausler merged commit d1e4a2d into llvm:main Sep 4, 2024
11 checks passed
@klausler klausler deleted the bug106705 branch September 4, 2024 17:54
@kkwli
Copy link
Collaborator

kkwli commented Sep 11, 2024

@klausler
Compiling smp-proc-ref.f90 hangs on AIX. It happens in calling ResolveSpecificationParts
in ExpressionAnalyzer::ResolveForward. Debugger does not yield any information! Any clues of where to look at are much appreciated.

@rorth
Copy link
Collaborator

rorth commented Sep 11, 2024

On Solaris/sparcv9, the new Semantics/smp-proc-ref.f90 testcase causes flang-new to SEGV:

RUN: at line 1: bin/flang-new -fc1 -fsyntax-only flang/test/Semantics/smp-proc-ref.f90
+ bin/flang-new -fc1 -fsyntax-only flang/test/Semantics/smp-proc-ref.f90
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/flang-new -fc1 -fsyntax-only flang/test/Semantics/smp-proc-ref.f90
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  flang-new 0x00000001078e6bb8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 36
1  flang-new 0x00000001078e74bc SignalHandler(int) + 896
2  libc.so.1 0x00007fffff0c6398 __sighndlr + 12
3  libc.so.1 0x00007fffff0b8c40 call_user_handler + 1024
4  libc.so.1 0x00007fffff0b9000 sigacthandler + 160
5  libc.so.1 0x00007ffffefd652c memcmp + 164
6  flang-new 0x0000000108368380 Fortran::semantics::Scope::FindSymbol(Fortran::parser::CharBlock const&) const + 48
7  flang-new 0x00000001082de780 Fortran::semantics::ScopeHandler::FindSymbol(Fortran::semantics::Scope const&, Fortran::parser::Name const&) + 276
8  flang-new 0x00000001082eb010 Fortran::semantics::ScopeHandler::FindSeparateModuleProcedureInterface(Fortran::parser::Name const&) + 36
9  flang-new 0x00000001082eb230 Fortran::semantics::SubprogramVisitor::BeginMpSubprogram(Fortran::parser::Name const&) + 36
10 flang-new 0x000000010830ce64 Fortran::semantics::ResolveNamesVisitor::BeginScopeForNode(Fortran::semantics::ProgramTree const&) + 348
11 flang-new 0x000000010830b840 Fortran::semantics::ResolveNamesVisitor::ResolveSpecificationParts(Fortran::semantics::ProgramTree&) + 48
12 flang-new 0x000000010830dd70 Fortran::semantics::ResolveSpecificationParts(Fortran::semantics::SemanticsContext&, Fortran::semantics::Symbol const&) + 192
13 flang-new 0x000000010822f680 Fortran::evaluate::ExpressionAnalyzer::ResolveForward(Fortran::semantics::Symbol const&) + 232
14 flang-new 0x0000000108230330 Fortran::evaluate::ExpressionAnalyzer::GetCalleeAndArguments(Fortran::parser::Name const&, std::vector<std::optional<Fortran::evaluate::ActualArgument>, std::allocator<std::optional<Fortran::evaluate::ActualArgument>>>&&, bool, bool) + 52
15 flang-new 0x0000000108231948 Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::FunctionReference const&, std::optional<Fortran::parser::StructureConstructor>*) + 348
16 flang-new 0x000000010823a894 std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>> Fortran::evaluate::ExpressionAnalyzer::ExprOrVariable<Fortran::parser::Expr>(Fortran::parser::Expr const&, Fortran::parser::CharBlock) + 860
17 flang-new 0x000000010823a420 Fortran::evaluate::ExpressionAnalyzer::IterativelyAnalyzeSubexpressions(Fortran::parser::Expr const&) + 1024
18 flang-new 0x00000001082221c0 Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::Expr const&) + 132
19 flang-new 0x00000001082419b4 Fortran::evaluate::ArgumentAnalyzer::AnalyzeExprOrWholeAssumedSizeArray(Fortran::parser::Expr const&) + 684
20 flang-new 0x00000001082415a8 Fortran::evaluate::ArgumentAnalyzer::AnalyzeExpr(Fortran::parser::Expr const&) + 452 
21 flang-new 0x0000000108233c5c Fortran::evaluate::ArgumentAnalyzer::Analyze(Fortran::parser::Expr const&) + 28
22 flang-new 0x0000000108233604 Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::AssignmentStmt const&) + 100
[...]

The SEGV happens for an unaligned/invalid address according to truss:

26345:      Incurred fault #6, FLTBOUNDS  %pc = 0x7FFFFEFD652C
26345:        siginfo: SIGSEGV SEGV_MAPERR addr=0x000000E1 
26345:      Received signal #11, SIGSEGV [caught]
26345:        siginfo: SIGSEGV SEGV_MAPERR addr=0x000000E1

Haven't investigated further yet. gdb shows

#0  0x00007ffffefd652c in memcmp () from /lib/64/libc.so.1
#1  0x0000000107d84ac8 in std::_Rb_tree<Fortran::parser::CharBlock, std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> >, std::_Select1st<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > >, std::less<Fortran::parser::CharBlock>, std::allocator<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > > >::find(Fortran::parser::CharBlock const&) const ()
#2  0x0000000108368388 in Fortran::semantics::Scope::FindSymbol(Fortran::parser::CharBlock const&) const ()
#3  0x00000001082de788 in Fortran::semantics::ScopeHandler::FindSymbol(Fortran::semantics::Scope const&, Fortran::parser::Name const&) ()
#4  0x00000001082eb018 in Fortran::semantics::ScopeHandler::FindSeparateModuleProcedureInterface(Fortran::parser::Name const&) ()
#5  0x00000001082eb238 in Fortran::semantics::SubprogramVisitor::BeginMpSubprogram(Fortran::parser::Name const&) ()
#6  0x000000010830ce6c in Fortran::semantics::ResolveNamesVisitor::BeginScopeForNode(Fortran::semantics::ProgramTree const&) ()
#7  0x000000010830b848 in Fortran::semantics::ResolveNamesVisitor::ResolveSpecificationParts(Fortran::semantics::ProgramTree&) ()
#8  0x000000010830dd78 in Fortran::semantics::ResolveSpecificationParts(Fortran::semantics::SemanticsContext&, Fortran::semantics::Symbol const&) ()
#9  0x000000010822f688 in Fortran::evaluate::ExpressionAnalyzer::ResolveForward(Fortran::semantics::Symbol const&) ()
#10 0x0000000108230338 in Fortran::evaluate::ExpressionAnalyzer::GetCalleeAndArguments(Fortran::parser::Name const&, std::vector<std::optional<Fortran::evaluate::ActualArgument>, std::allocator<std::optional<Fortran::evaluate::ActualArgument> > >&&, bool, bool) ()
#11 0x0000000108231950 in Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::FunctionReference const&, std::optional<Fortran::parser::StructureConstructor>*) ()
#12 0x000000010823a89c in std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType> > Fortran::evaluate::ExpressionAnalyzer::ExprOrVariable<Fortran::parser::Expr>(Fortran::parser::Expr const&, Fortran::parser::CharBlock) ()
#13 0x000000010823a428 in Fortran::evaluate::ExpressionAnalyzer::IterativelyAnalyzeSubexpressions(Fortran::parser::Expr const&) ()
#14 0x00000001082221c8 in Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::Expr const&) ()
#15 0x00000001082419bc in Fortran::evaluate::ArgumentAnalyzer::AnalyzeExprOrWholeAssumedSizeArray(Fortran::parser::Expr const&) ()
#16 0x00000001082415b0 in Fortran::evaluate::ArgumentAnalyzer::AnalyzeExpr(Fortran::parser::Expr const&) ()
#17 0x0000000108233c64 in Fortran::evaluate::ArgumentAnalyzer::Analyze(Fortran::parser::Expr const&) ()
#18 0x000000010823360c in Fortran::evaluate::ExpressionAnalyzer::Analyze(Fortran::parser::AssignmentStmt const&) ()
[...]

but that's not particularly useful in a Release build.

@klausler
Copy link
Contributor Author

That's an important clue. Would you be willing to try a possible fix for me? I can't test in your environments.

@klausler
Copy link
Contributor Author

#108271 is an experimental patch.

@rorth
Copy link
Collaborator

rorth commented Sep 26, 2024

I've now finally done a Debug build. Here's what I found:

The SEGV happens here:

Thread 2 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
0x00007ffffefd652c in memcmp () from /lib/64/libc.so.1
1: x/i $pc
=> 0x7ffffefd652c <memcmp+164>:	ldub  [ %o0 + %o1 ], %o5
(gdb) p/x $o0
$9 = 0x142917167
(gdb) p/x $o1
$10 = 0xfffffffebd6e8efa
(gdb) p/x $o0+$o1
$11 = 0x61

In the caller I see

#1  0x000000012cab7458 in Fortran::parser::CharBlock::Compare (
    this=0x1428cfd90, that=...)
    at /vol/llvm/src/llvm-project/local/flang/include/flang/Parser/char-block.h:141
141	      int cmp{std::memcmp(static_cast<const void *>(begin()),

(gdb) p begin()
$12 = 0x142917167 "m\nreal :: qux(10)\ninterface\nmodule subroutine bar(i)\nend\nmodule function baz()\nend\nend interface\nend\nsubmodule(m) sm\ncontains\nmodule procedure bar\nqux(i) = baz()\nend\nmodule procedure baz\nbaz = 1.\nend\n"...
(gdb) p that.begin()
$13 = 0x61 <error: Cannot access memory at address 0x61>
(gdb) p bytes
$14 = 1

ISTM that instead of passing the address of the second string to memcmp, the first element (0x61 == 'a') is passed instead. I suspect this happens further up in the callers

#16 0x000000012e321a74 in Fortran::evaluate::ExpressionAnalyzer::ResolveForward
    (this=0xffffffff7fff54d8, symbol=...)
    at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/expression.cpp:2677
2677	      semantics::ResolveSpecificationParts(context_, symbol);

I suspect this is here in your patch:

@@ -2661,8 +2661,13 @@ bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
       // checking a specification expression in a sibling module
       // procedure.  Resolve its names now so that its interface
       // is known.
+      const semantics::Scope &scope{symbol.owner()};
       semantics::ResolveSpecificationParts(context_, symbol);
-      if (symbol.has<semantics::SubprogramNameDetails>()) {
+      const Symbol *resolved{nullptr};
+      if (auto iter{scope.find(symbol.name())}; iter != scope.cend()) {
+        resolved = &*iter->second;
+      }
+      if (!resolved || resolved->has<semantics::SubprogramNameDetails>()) {
         // When the symbol hasn't had its details updated, we must have
         // already been in the process of resolving the function's
         // specification part; but recursive function calls are not

@klausler
Copy link
Contributor Author

The changes to ResolveForward() in the patch follow the call to ResolveSpecificationParts(), though. And the experimental patch that you tried for me (capturing symbol.name() before that call) didn't solve the problem.

What are the source locations in the call chain between #1 and #16?

@rorth
Copy link
Collaborator

rorth commented Sep 27, 2024

#0  0x00007ffffefd652c in memcmp () from /lib/64/libc.so.1
#1  0x000000012cab7458 in Fortran::parser::CharBlock::Compare (this=0x1428cfd90, that=...) at /vol/llvm/src/llvm-project/local/flang/include/flang/Parser/char-block.h:141
#2  0x000000012cab72b8 in Fortran::parser::CharBlock::operator< (this=0x1428cfd90, that=...) at /vol/llvm/src/llvm-project/local/flang/include/flang/Parser/char-block.h:109
#3  0x000000012cb67874 in std::less<Fortran::parser::CharBlock>::operator() (this=0x1429162c8, __x=..., __y=...) at /usr/gcc/14/include/c++/14.2.0/bits/stl_function.h:405
#4  0x000000012cb6a74c in std::_Rb_tree<Fortran::parser::CharBlock, std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> >, std::_Select1st<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > >, std::less<Fortran::parser::CharBlock>, std::allocator<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > > >::_M_lower_bound (this=0x1429162c8, __x=0x1428cfd70, __y=0x1429162d0, __k=...) at /usr/gcc/14/include/c++/14.2.0/bits/stl_tree.h:1964
#5  0x000000012cb06844 in std::_Rb_tree<Fortran::parser::CharBlock, std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> >, std::_Select1st<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > >, std::less<Fortran::parser::CharBlock>, std::allocator<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > > >::find (this=0x1429162c8, __k=...) at /usr/gcc/14/include/c++/14.2.0/bits/stl_tree.h:2541
#6  0x000000012cada4f0 in std::map<Fortran::parser::CharBlock, Fortran::common::Reference<Fortran::semantics::Symbol>, std::less<Fortran::parser::CharBlock>, std::allocator<std::pair<Fortran::parser::CharBlock const, Fortran::common::Reference<Fortran::semantics::Symbol> > > >::find (this=0x1429162c8, __x=...) at /usr/gcc/14/include/c++/14.2.0/bits/stl_map.h:1244
#7  0x000000012cac4094 in Fortran::semantics::Scope::find (this=0x142916268, name=...) at /vol/llvm/src/llvm-project/local/flang/include/flang/Semantics/scope.h:148
#8  0x000000012e7a1f1c in Fortran::semantics::Scope::FindSymbol (this=0x142916268, name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/scope.cpp:89
#9  0x000000012e550d40 in Fortran::semantics::ScopeHandler::FindSymbol (this=0xffffffff7fff02e0, scope=..., name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:2441
#10 0x000000012e550c18 in Fortran::semantics::ScopeHandler::FindSymbol (this=0xffffffff7fff02e0, name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:2426
#11 0x000000012e55e5b4 in Fortran::semantics::ScopeHandler::FindSeparateModuleProcedureInterface (this=0xffffffff7fff02e0, name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:4308
#12 0x000000012e55e7f4 in Fortran::semantics::SubprogramVisitor::BeginMpSubprogram (this=0xffffffff7fff0220, name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:4334
#13 0x000000012e582d24 in Fortran::semantics::ResolveNamesVisitor::BeginScopeForNode (this=0xffffffff7fff0138, node=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:9391
#14 0x000000012e582040 in Fortran::semantics::ResolveNamesVisitor::ResolveSpecificationParts (this=0xffffffff7fff0138, node=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:9274
#15 0x000000012e583de4 in Fortran::semantics::ResolveSpecificationParts (context=..., subprogram=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/resolve-names.cpp:9667
#16 0x000000012e321a74 in Fortran::evaluate::ExpressionAnalyzer::ResolveForward (this=0xffffffff7fff5198, symbol=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/expression.cpp:2677
#17 0x000000012e3231e8 in Fortran::evaluate::ExpressionAnalyzer::GetCalleeAndArguments (this=0xffffffff7fff5198, name=..., arguments=..., isSubroutine=false, mightBeStructureConstructor=true) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/expression.cpp:2886
#18 0x000000012e323040 in operator() (__closure=0xffffffff7fff1018, name=...) at /vol/llvm/src/llvm-project/local/flang/lib/Semantics/expression.cpp:2869

@klausler
Copy link
Contributor Author

It looks like one of the CharBlock-typed names used as a std::map<> key in that scope's symbol table have gotten clobbered. Dumping the scope (if (getenv("MYDEBUG")) llvm::errs() << scope; or calling SemanticsContext::DumpSymbols(llvm::errs())) should also crash at that point if this is the case. Are memory watchpoints working in your debugging environment?

@rorth
Copy link
Collaborator

rorth commented Oct 1, 2024

When printing the scope arg from frame #9 in gdb, the output looks fine. However, this may well be gdb guarding
against invalid accesses.

Solaris gdb does support watchpoints, btw.

@rorth
Copy link
Collaborator

rorth commented Oct 8, 2024

Sorry I got distracted for a while. With dumping scope in ScopeHandler::FindSymbol, I get the attached.
smp.txt

@klausler
Copy link
Contributor Author

klausler commented Oct 8, 2024

These are valuable clues; thanks! I think I know what's wrong, and should soon have a patch to test.

@klausler
Copy link
Contributor Author

klausler commented Oct 8, 2024

#111582

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang][Semantics] Semantic error in Fortran code due to recursive reference in specification expression
4 participants