Skip to content

Commit df6219c

Browse files
committed
[flang] Fix references to destroyed objects
ProgramTree instances are created as the value of a local variable in the Pre(const parser::ProgramUnit &) member function in name resolution. But references to these ProgramTree instances can persist in SubprogramNameDetails symbol table entries that might survive that function call's lifetime, and lead to trouble later when (e.g.) expression semantics needs to deal with a possible forward reference in a function reference in an expression being processed later in expression checking. So put those ProgramTree instances into a longer-lived linked list within the SemanticsContext. Might fix some weird crashes reported on big-endian targets (AIX & Solaris).
1 parent 70cbedc commit df6219c

File tree

8 files changed

+50
-47
lines changed

8 files changed

+50
-47
lines changed

flang/lib/Semantics/program-tree.h renamed to flang/include/flang/Semantics/program-tree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_
1010
#define FORTRAN_SEMANTICS_PROGRAM_TREE_H_
1111

12+
#include "symbol.h"
1213
#include "flang/Parser/parse-tree.h"
13-
#include "flang/Semantics/symbol.h"
1414
#include <list>
1515
#include <variant>
1616

@@ -35,7 +35,7 @@ class ProgramTree {
3535
std::list<common::Reference<const parser::GenericSpec>>;
3636

3737
// Build the ProgramTree rooted at one of these program units.
38-
static ProgramTree Build(const parser::ProgramUnit &, SemanticsContext &);
38+
static ProgramTree &Build(const parser::ProgramUnit &, SemanticsContext &);
3939
static std::optional<ProgramTree> Build(
4040
const parser::MainProgram &, SemanticsContext &);
4141
static std::optional<ProgramTree> Build(

flang/include/flang/Semantics/semantics.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef FORTRAN_SEMANTICS_SEMANTICS_H_
1010
#define FORTRAN_SEMANTICS_SEMANTICS_H_
1111

12+
#include "module-dependences.h"
13+
#include "program-tree.h"
1214
#include "scope.h"
1315
#include "symbol.h"
1416
#include "flang/Common/Fortran-features.h"
@@ -17,7 +19,6 @@
1719
#include "flang/Evaluate/intrinsics.h"
1820
#include "flang/Evaluate/target.h"
1921
#include "flang/Parser/message.h"
20-
#include "flang/Semantics/module-dependences.h"
2122
#include <iosfwd>
2223
#include <set>
2324
#include <string>
@@ -280,6 +281,9 @@ class SemanticsContext {
280281

281282
void DumpSymbols(llvm::raw_ostream &);
282283

284+
// Top-level ProgramTrees are owned by the SemanticsContext for persistence.
285+
ProgramTree &SaveProgramTree(ProgramTree &&);
286+
283287
private:
284288
struct ScopeIndexComparator {
285289
bool operator()(parser::CharBlock, parser::CharBlock) const;
@@ -331,6 +335,7 @@ class SemanticsContext {
331335
ModuleDependences moduleDependences_;
332336
std::map<const Symbol *, SourceName> moduleFileOutputRenamings_;
333337
UnorderedSymbolSet isDefined_;
338+
std::list<ProgramTree> programTrees_;
334339
};
335340

336341
class Semantics {

flang/lib/Semantics/program-tree.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "program-tree.h"
9+
#include "flang/Semantics/program-tree.h"
1010
#include "flang/Common/idioms.h"
1111
#include "flang/Parser/char-block.h"
1212
#include "flang/Semantics/scope.h"
@@ -130,13 +130,13 @@ static ProgramTree BuildModuleTree(
130130
return node;
131131
}
132132

133-
ProgramTree ProgramTree::Build(
133+
ProgramTree &ProgramTree::Build(
134134
const parser::ProgramUnit &x, SemanticsContext &context) {
135135
return common::visit(
136-
[&](const auto &y) {
136+
[&](const auto &y) -> ProgramTree & {
137137
auto node{Build(y.value(), context)};
138138
CHECK(node.has_value());
139-
return std::move(*node);
139+
return context.SaveProgramTree(std::move(*node));
140140
},
141141
x.u);
142142
}

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

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ using common::NumericOperator;
3131
using common::RelationalOperator;
3232
using IntrinsicOperator = parser::DefinedOperator::IntrinsicOperator;
3333

34-
static constexpr const char *operatorPrefix{"operator("};
35-
3634
static GenericKind MapIntrinsicOperator(IntrinsicOperator);
3735

3836
Symbol *Resolve(const parser::Name &name, Symbol *symbol) {
@@ -69,37 +67,6 @@ bool IsIntrinsicOperator(
6967
return false;
7068
}
7169

72-
template <typename E>
73-
std::forward_list<std::string> GetOperatorNames(
74-
const SemanticsContext &context, E opr) {
75-
std::forward_list<std::string> result;
76-
for (const char *name : context.languageFeatures().GetNames(opr)) {
77-
result.emplace_front(std::string{operatorPrefix} + name + ')');
78-
}
79-
return result;
80-
}
81-
82-
std::forward_list<std::string> GetAllNames(
83-
const SemanticsContext &context, const SourceName &name) {
84-
std::string str{name.ToString()};
85-
if (!name.empty() && name.end()[-1] == ')' &&
86-
name.ToString().rfind(std::string{operatorPrefix}, 0) == 0) {
87-
for (int i{0}; i != common::LogicalOperator_enumSize; ++i) {
88-
auto names{GetOperatorNames(context, LogicalOperator{i})};
89-
if (llvm::is_contained(names, str)) {
90-
return names;
91-
}
92-
}
93-
for (int i{0}; i != common::RelationalOperator_enumSize; ++i) {
94-
auto names{GetOperatorNames(context, RelationalOperator{i})};
95-
if (llvm::is_contained(names, str)) {
96-
return names;
97-
}
98-
}
99-
}
100-
return {str};
101-
}
102-
10370
bool IsLogicalConstant(
10471
const SemanticsContext &context, const SourceName &name) {
10572
std::string str{name.ToString()};

flang/lib/Semantics/resolve-names-utils.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ parser::MessageFixedText WithSeverity(
5151
bool IsIntrinsicOperator(const SemanticsContext &, const SourceName &);
5252
bool IsLogicalConstant(const SemanticsContext &, const SourceName &);
5353

54-
// Some intrinsic operators have more than one name (e.g. `operator(.eq.)` and
55-
// `operator(==)`). GetAllNames() returns them all, including symbolName.
56-
std::forward_list<std::string> GetAllNames(
57-
const SemanticsContext &, const SourceName &);
58-
5954
template <typename T>
6055
MaybeIntExpr EvaluateIntExpr(SemanticsContext &context, const T &expr) {
6156
if (MaybeExpr maybeExpr{

flang/lib/Semantics/resolve-names.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "definable.h"
1111
#include "mod-file.h"
1212
#include "pointer-assignment.h"
13-
#include "program-tree.h"
1413
#include "resolve-directives.h"
1514
#include "resolve-names-utils.h"
1615
#include "rewrite-parse-tree.h"
@@ -32,6 +31,7 @@
3231
#include "flang/Parser/tools.h"
3332
#include "flang/Semantics/attr.h"
3433
#include "flang/Semantics/expression.h"
34+
#include "flang/Semantics/program-tree.h"
3535
#include "flang/Semantics/scope.h"
3636
#include "flang/Semantics/semantics.h"
3737
#include "flang/Semantics/symbol.h"
@@ -2490,6 +2490,7 @@ Symbol &ScopeHandler::CopySymbol(const SourceName &name, const Symbol &symbol) {
24902490
}
24912491

24922492
// Look for name only in scope, not in enclosing scopes.
2493+
24932494
Symbol *ScopeHandler::FindInScope(
24942495
const Scope &scope, const parser::Name &name) {
24952496
return Resolve(name, FindInScope(scope, name.source));
@@ -9120,7 +9121,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
91209121
ResolveAccParts(context(), x, &topScope_);
91219122
return false;
91229123
}
9123-
auto root{ProgramTree::Build(x, context())};
9124+
ProgramTree &root{ProgramTree::Build(x, context())};
91249125
SetScope(topScope_);
91259126
ResolveSpecificationParts(root);
91269127
FinishSpecificationParts(root);

flang/lib/Semantics/semantics.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,10 @@ void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
663663
DoDumpSymbols(os, globalScope());
664664
}
665665

666+
ProgramTree &SemanticsContext::SaveProgramTree(ProgramTree &&tree) {
667+
return programTrees_.emplace_back(std::move(tree));
668+
}
669+
666670
void Semantics::DumpSymbols(llvm::raw_ostream &os) { context_.DumpSymbols(os); }
667671

668672
void Semantics::DumpSymbolsSources(llvm::raw_ostream &os) const {

flang/lib/Semantics/tools.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,37 @@ bool HasDefinedIo(common::DefinedIo which, const DerivedTypeSpec &derived,
16541654
return parentType && HasDefinedIo(which, *parentType, scope);
16551655
}
16561656

1657+
template <typename E>
1658+
std::forward_list<std::string> GetOperatorNames(
1659+
const SemanticsContext &context, E opr) {
1660+
std::forward_list<std::string> result;
1661+
for (const char *name : context.languageFeatures().GetNames(opr)) {
1662+
result.emplace_front("operator("s + name + ')');
1663+
}
1664+
return result;
1665+
}
1666+
1667+
std::forward_list<std::string> GetAllNames(
1668+
const SemanticsContext &context, const SourceName &name) {
1669+
std::string str{name.ToString()};
1670+
if (!name.empty() && name.end()[-1] == ')' &&
1671+
name.ToString().rfind("operator(", 0) == 0) {
1672+
for (int i{0}; i != common::LogicalOperator_enumSize; ++i) {
1673+
auto names{GetOperatorNames(context, common::LogicalOperator{i})};
1674+
if (llvm::is_contained(names, str)) {
1675+
return names;
1676+
}
1677+
}
1678+
for (int i{0}; i != common::RelationalOperator_enumSize; ++i) {
1679+
auto names{GetOperatorNames(context, common::RelationalOperator{i})};
1680+
if (llvm::is_contained(names, str)) {
1681+
return names;
1682+
}
1683+
}
1684+
}
1685+
return {str};
1686+
}
1687+
16571688
void WarnOnDeferredLengthCharacterScalar(SemanticsContext &context,
16581689
const SomeExpr *expr, parser::CharBlock at, const char *what) {
16591690
if (context.languageFeatures().ShouldWarn(

0 commit comments

Comments
 (0)