namespace Fortran::parser {
-Parsing::Parsing() {}
Parsing::Parsing(AllSources &s) : cooked_{s} {}
-
Parsing::~Parsing() {}
void Parsing::Prescan(const std::string &path, Options options) {
class Parsing {
public:
- Parsing();
- explicit Parsing(AllSources &); // to share an extant AllSources instance
-
+ explicit Parsing(AllSources &);
~Parsing();
bool consumedWholeFile() const { return consumedWholeFile_; }
-// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
return origin_[low];
}
-CookedSource::CookedSource() : allSources_{new AllSources} {}
-CookedSource::CookedSource(AllSources &s) : allSources_{&s} {}
+CookedSource::CookedSource(AllSources &s) : allSources_{s} {}
CookedSource::~CookedSource() {}
std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
void CookedSource::Marshal() {
CHECK(provenanceMap_.size() == buffer_.size());
- provenanceMap_.Put(
- allSources_->AddCompilerInsertion("(after end of source)"));
+ provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));
data_ = buffer_.Marshal();
buffer_.clear();
}
std::ostream &CookedSource::Dump(std::ostream &o) const {
o << "CookedSource:\n";
- allSources_->Dump(o);
+ allSources_.Dump(o);
o << "CookedSource::provenanceMap_:\n";
provenanceMap_.Dump(o);
return o;
-// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
#include "source.h"
#include "../common/idioms.h"
#include "../common/interval.h"
-#include "../common/reference-counted.h"
#include <cstddef>
#include <map>
#include <memory>
std::vector<ContiguousProvenanceMapping> provenanceMap_;
};
-// AllSources is reference-counted so that multiple instances of CookedSource
-// can share an AllSources instance.
-class AllSources : public common::ReferenceCounted<AllSources> {
+// A singleton AllSources instance for the whole compilation
+// is shared by reference.
+class AllSources {
public:
AllSources();
~AllSources();
class CookedSource {
public:
- CookedSource();
explicit CookedSource(AllSources &);
~CookedSource();
- AllSources &allSources() { return *allSources_; }
- const AllSources &allSources() const { return *allSources_; }
+ AllSources &allSources() { return allSources_; }
+ const AllSources &allSources() const { return allSources_; }
const std::string &data() const { return data_; }
bool IsValid(const char *p) const {
bool IsValid(CharBlock range) const {
return !range.empty() && IsValid(range.begin()) && IsValid(range.end() - 1);
}
- bool IsValid(ProvenanceRange r) const { return allSources_->IsValid(r); }
+ bool IsValid(ProvenanceRange r) const { return allSources_.IsValid(r); }
std::optional<ProvenanceRange> GetProvenanceRange(CharBlock) const;
std::ostream &Dump(std::ostream &) const;
private:
- common::CountedReference<AllSources> allSources_;
+ AllSources &allSources_;
CharBuffer buffer_; // before Marshal()
std::string data_; // all of it, prescanned and preprocessed
OffsetToProvenanceMappings provenanceMap_;
#include <optional>
#include <set>
-// #define DUMP_ON_FAILURE 1
+#define DUMP_ON_FAILURE 1 // TODO pmk rm
// #define CRASH_ON_FAILURE 1
#if DUMP_ON_FAILURE
#include "../parser/dump-parse-tree.h"
"Module file for '%s' has invalid checksum: %s"_err_en_US, name, *path);
return nullptr;
}
- // TODO: Construct parsing with an AllSources reference to share provenance
- parser::Parsing parsing;
+ parser::Parsing parsing{context_.allSources()};
parser::Options options;
options.isModuleFile = true;
parsing.Prescan(*path, options);
return nullptr;
}
auto &modSymbol{*it->second};
- // TODO: Preserve the CookedSource rather than acquiring its string.
- modSymbol.scope()->set_chars(std::string{parsing.cooked().AcquireData()});
modSymbol.set(Symbol::Flag::ModFile);
+ modSymbol.scope()->set_chars(parsing.cooked());
return modSymbol.scope();
}
category, DerivedTypeSpec{std::move(spec)});
}
+void Scope::set_chars(parser::CookedSource &cooked) {
+ CHECK(kind_ == Kind::Module);
+ CHECK(parent_.kind_ == Kind::Global || parent_.IsModuleFile());
+ CHECK(symbol_ != nullptr);
+ CHECK(symbol_->test(Symbol::Flag::ModFile));
+ // TODO: Preserve the CookedSource rather than acquiring its string.
+ chars_ = cooked.AcquireData();
+}
+
Scope::ImportKind Scope::GetImportKind() const {
if (importKind_) {
return *importKind_;
}
Scope *Scope::FindScope(parser::CharBlock source) {
- if (!sourceRange_.Contains(source)) {
+ bool isContained{sourceRange_.Contains(source)};
+ if (!isContained && kind_ != Kind::Global && !IsModuleFile()) {
return nullptr;
}
for (auto &child : children_) {
return scope;
}
}
- return this;
+ return isContained ? this : nullptr;
}
void Scope::AddSourceRange(const parser::CharBlock &source) {
#include "../common/Fortran.h"
#include "../common/idioms.h"
#include "../parser/message.h"
+#include "../parser/provenance.h"
#include <list>
#include <map>
#include <set>
using mapType = std::map<SourceName, Symbol *>;
public:
- ENUM_CLASS(Kind, System, Global, Module, MainProgram, Subprogram, DerivedType,
- Block, Forall, ImpliedDos)
+ ENUM_CLASS(Kind, Global, Module, MainProgram, Subprogram, DerivedType, Block,
+ Forall, ImpliedDos)
using ImportKind = common::ImportKind;
// Create the Global scope -- the root of the scope tree
bool operator!=(const Scope &that) const { return this != &that; }
Scope &parent() {
- CHECK(kind_ != Kind::System);
+ CHECK(&parent_ != this);
return parent_;
}
const Scope &parent() const {
- CHECK(kind_ != Kind::System);
+ CHECK(&parent_ != this);
return parent_;
}
Kind kind() const { return kind_; }
// For modules read from module files, this is the stream of characters
// that are referenced by SourceName objects.
- void set_chars(std::string &&chars) { chars_ = std::move(chars); }
+ void set_chars(parser::CookedSource &);
ImportKind GetImportKind() const;
// Names appearing in IMPORT statements in this scope
const DeclTypeSpec &InstantiateIntrinsicType(
const DeclTypeSpec &, SemanticsContext &);
+ bool IsModuleFile() const {
+ return kind_ == Kind::Module && symbol_ != nullptr &&
+ symbol_->test(Symbol::Flag::ModFile);
+ }
+
private:
Scope &parent_; // this is enclosing scope, not extended derived type base
const Kind kind_;
SemanticsContext::SemanticsContext(
const common::IntrinsicTypeDefaultKinds &defaultKinds,
- const parser::LanguageFeatureControl &languageFeatures)
+ const parser::LanguageFeatureControl &languageFeatures,
+ parser::AllSources &allSources)
: defaultKinds_{defaultKinds}, languageFeatures_{languageFeatures},
+ allSources_{allSources},
intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds)},
foldingContext_{evaluate::FoldingContext{
parser::ContextualMessages{parser::CharBlock{}, &messages_}}} {}
+SemanticsContext::~SemanticsContext() {}
+
bool SemanticsContext::IsEnabled(parser::LanguageFeature feature) const {
return languageFeatures_.IsEnabled(feature);
}
class SemanticsContext {
public:
SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
- const parser::LanguageFeatureControl &);
+ const parser::LanguageFeatureControl &, parser::AllSources &);
+ ~SemanticsContext();
const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
return defaultKinds_;
Scope &globalScope() { return globalScope_; }
parser::Messages &messages() { return messages_; }
evaluate::FoldingContext &foldingContext() { return foldingContext_; }
+ parser::AllSources &allSources() { return allSources_; }
SemanticsContext &set_location(const parser::CharBlock *location) {
location_ = location;
private:
const common::IntrinsicTypeDefaultKinds &defaultKinds_;
const parser::LanguageFeatureControl &languageFeatures_;
+ parser::AllSources &allSources_;
const parser::CharBlock *location_{nullptr};
std::vector<std::string> searchDirectories_;
std::string moduleDirectory_{"."s};
case Scope::Kind::Module:
case Scope::Kind::MainProgram:
case Scope::Kind::Subprogram: return scope;
- case Scope::Kind::Global:
- case Scope::Kind::System: return nullptr;
+ case Scope::Kind::Global: return nullptr;
case Scope::Kind::DerivedType:
case Scope::Kind::Block:
case Scope::Kind::Forall:
}
private:
- parser::CookedSource cooked_;
+ parser::AllSources allSources_;
+ parser::CookedSource cooked_{allSources_};
std::map<std::string, std::size_t> offsets_;
};
}
}
options.searchDirectories = driver.searchDirectories;
- Fortran::parser::Parsing parsing;
+ Fortran::parser::AllSources allSources;
+ Fortran::parser::Parsing parsing{allSources};
auto start{CPUseconds()};
parsing.Prescan(path, options);
}
}
options.searchDirectories = driver.searchDirectories;
- Fortran::parser::Parsing parsing;
+ Fortran::parser::Parsing parsing{semanticsContext.allSources()};
parsing.Prescan(path, options);
if (!parsing.messages().empty() &&
(driver.warningsAreErrors || parsing.messages().AnyFatalError())) {
options.predefinitions.emplace_back("__F18_MAJOR__", "1");
options.predefinitions.emplace_back("__F18_MINOR__", "1");
options.predefinitions.emplace_back("__F18_PATCHLEVEL__", "1");
+#if __x86_64__
+ options.predefinitions.emplace_back("__x86_64__", "1");
+#endif
Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;
driver.pgf90Args.push_back("-mp");
}
+ Fortran::parser::AllSources allSources;
Fortran::semantics::SemanticsContext semanticsContext{
- defaultKinds, options.features};
+ defaultKinds, options.features, allSources};
semanticsContext.set_moduleDirectory(driver.moduleDirectory)
.set_moduleFileSuffix(driver.moduleFileSuffix)
.set_searchDirectories(driver.searchDirectories)