Skip to content

Commit

Permalink
[flang] Fix references to destroyed objects
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
klausler committed Oct 8, 2024
1 parent 70cbedc commit df6219c
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_
#define FORTRAN_SEMANTICS_PROGRAM_TREE_H_

#include "symbol.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/symbol.h"
#include <list>
#include <variant>

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

// Build the ProgramTree rooted at one of these program units.
static ProgramTree Build(const parser::ProgramUnit &, SemanticsContext &);
static ProgramTree &Build(const parser::ProgramUnit &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::MainProgram &, SemanticsContext &);
static std::optional<ProgramTree> Build(
Expand Down
7 changes: 6 additions & 1 deletion flang/include/flang/Semantics/semantics.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef FORTRAN_SEMANTICS_SEMANTICS_H_
#define FORTRAN_SEMANTICS_SEMANTICS_H_

#include "module-dependences.h"
#include "program-tree.h"
#include "scope.h"
#include "symbol.h"
#include "flang/Common/Fortran-features.h"
Expand All @@ -17,7 +19,6 @@
#include "flang/Evaluate/intrinsics.h"
#include "flang/Evaluate/target.h"
#include "flang/Parser/message.h"
#include "flang/Semantics/module-dependences.h"
#include <iosfwd>
#include <set>
#include <string>
Expand Down Expand Up @@ -280,6 +281,9 @@ class SemanticsContext {

void DumpSymbols(llvm::raw_ostream &);

// Top-level ProgramTrees are owned by the SemanticsContext for persistence.
ProgramTree &SaveProgramTree(ProgramTree &&);

private:
struct ScopeIndexComparator {
bool operator()(parser::CharBlock, parser::CharBlock) const;
Expand Down Expand Up @@ -331,6 +335,7 @@ class SemanticsContext {
ModuleDependences moduleDependences_;
std::map<const Symbol *, SourceName> moduleFileOutputRenamings_;
UnorderedSymbolSet isDefined_;
std::list<ProgramTree> programTrees_;
};

class Semantics {
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Semantics/program-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include "program-tree.h"
#include "flang/Semantics/program-tree.h"
#include "flang/Common/idioms.h"
#include "flang/Parser/char-block.h"
#include "flang/Semantics/scope.h"
Expand Down Expand Up @@ -130,13 +130,13 @@ static ProgramTree BuildModuleTree(
return node;
}

ProgramTree ProgramTree::Build(
ProgramTree &ProgramTree::Build(
const parser::ProgramUnit &x, SemanticsContext &context) {
return common::visit(
[&](const auto &y) {
[&](const auto &y) -> ProgramTree & {
auto node{Build(y.value(), context)};
CHECK(node.has_value());
return std::move(*node);
return context.SaveProgramTree(std::move(*node));
},
x.u);
}
Expand Down
33 changes: 0 additions & 33 deletions flang/lib/Semantics/resolve-names-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ using common::NumericOperator;
using common::RelationalOperator;
using IntrinsicOperator = parser::DefinedOperator::IntrinsicOperator;

static constexpr const char *operatorPrefix{"operator("};

static GenericKind MapIntrinsicOperator(IntrinsicOperator);

Symbol *Resolve(const parser::Name &name, Symbol *symbol) {
Expand Down Expand Up @@ -69,37 +67,6 @@ bool IsIntrinsicOperator(
return false;
}

template <typename E>
std::forward_list<std::string> GetOperatorNames(
const SemanticsContext &context, E opr) {
std::forward_list<std::string> result;
for (const char *name : context.languageFeatures().GetNames(opr)) {
result.emplace_front(std::string{operatorPrefix} + name + ')');
}
return result;
}

std::forward_list<std::string> GetAllNames(
const SemanticsContext &context, const SourceName &name) {
std::string str{name.ToString()};
if (!name.empty() && name.end()[-1] == ')' &&
name.ToString().rfind(std::string{operatorPrefix}, 0) == 0) {
for (int i{0}; i != common::LogicalOperator_enumSize; ++i) {
auto names{GetOperatorNames(context, LogicalOperator{i})};
if (llvm::is_contained(names, str)) {
return names;
}
}
for (int i{0}; i != common::RelationalOperator_enumSize; ++i) {
auto names{GetOperatorNames(context, RelationalOperator{i})};
if (llvm::is_contained(names, str)) {
return names;
}
}
}
return {str};
}

bool IsLogicalConstant(
const SemanticsContext &context, const SourceName &name) {
std::string str{name.ToString()};
Expand Down
5 changes: 0 additions & 5 deletions flang/lib/Semantics/resolve-names-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ parser::MessageFixedText WithSeverity(
bool IsIntrinsicOperator(const SemanticsContext &, const SourceName &);
bool IsLogicalConstant(const SemanticsContext &, const SourceName &);

// Some intrinsic operators have more than one name (e.g. `operator(.eq.)` and
// `operator(==)`). GetAllNames() returns them all, including symbolName.
std::forward_list<std::string> GetAllNames(
const SemanticsContext &, const SourceName &);

template <typename T>
MaybeIntExpr EvaluateIntExpr(SemanticsContext &context, const T &expr) {
if (MaybeExpr maybeExpr{
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "definable.h"
#include "mod-file.h"
#include "pointer-assignment.h"
#include "program-tree.h"
#include "resolve-directives.h"
#include "resolve-names-utils.h"
#include "rewrite-parse-tree.h"
Expand All @@ -32,6 +31,7 @@
#include "flang/Parser/tools.h"
#include "flang/Semantics/attr.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/program-tree.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"
Expand Down Expand Up @@ -2490,6 +2490,7 @@ Symbol &ScopeHandler::CopySymbol(const SourceName &name, const Symbol &symbol) {
}

// Look for name only in scope, not in enclosing scopes.

Symbol *ScopeHandler::FindInScope(
const Scope &scope, const parser::Name &name) {
return Resolve(name, FindInScope(scope, name.source));
Expand Down Expand Up @@ -9120,7 +9121,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
ResolveAccParts(context(), x, &topScope_);
return false;
}
auto root{ProgramTree::Build(x, context())};
ProgramTree &root{ProgramTree::Build(x, context())};
SetScope(topScope_);
ResolveSpecificationParts(root);
FinishSpecificationParts(root);
Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Semantics/semantics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,10 @@ void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
DoDumpSymbols(os, globalScope());
}

ProgramTree &SemanticsContext::SaveProgramTree(ProgramTree &&tree) {
return programTrees_.emplace_back(std::move(tree));
}

void Semantics::DumpSymbols(llvm::raw_ostream &os) { context_.DumpSymbols(os); }

void Semantics::DumpSymbolsSources(llvm::raw_ostream &os) const {
Expand Down
31 changes: 31 additions & 0 deletions flang/lib/Semantics/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,37 @@ bool HasDefinedIo(common::DefinedIo which, const DerivedTypeSpec &derived,
return parentType && HasDefinedIo(which, *parentType, scope);
}

template <typename E>
std::forward_list<std::string> GetOperatorNames(
const SemanticsContext &context, E opr) {
std::forward_list<std::string> result;
for (const char *name : context.languageFeatures().GetNames(opr)) {
result.emplace_front("operator("s + name + ')');
}
return result;
}

std::forward_list<std::string> GetAllNames(
const SemanticsContext &context, const SourceName &name) {
std::string str{name.ToString()};
if (!name.empty() && name.end()[-1] == ')' &&
name.ToString().rfind("operator(", 0) == 0) {
for (int i{0}; i != common::LogicalOperator_enumSize; ++i) {
auto names{GetOperatorNames(context, common::LogicalOperator{i})};
if (llvm::is_contained(names, str)) {
return names;
}
}
for (int i{0}; i != common::RelationalOperator_enumSize; ++i) {
auto names{GetOperatorNames(context, common::RelationalOperator{i})};
if (llvm::is_contained(names, str)) {
return names;
}
}
}
return {str};
}

void WarnOnDeferredLengthCharacterScalar(SemanticsContext &context,
const SomeExpr *expr, parser::CharBlock at, const char *what) {
if (context.languageFeatures().ShouldWarn(
Expand Down

0 comments on commit df6219c

Please sign in to comment.