From: peter klausler Date: Thu, 8 Feb 2018 00:24:02 +0000 (-0800) Subject: [flang] Development of character provenance. X-Git-Tag: llvmorg-12-init~9537^2~2938 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3558c22101d800983083ccdb9da679dd41570410;p=platform%2Fupstream%2Fllvm.git [flang] Development of character provenance. Original-commit: flang-compiler/f18@88c532958006ad064cab88d2405055a456b07dcf Reviewed-on: https://github.com/flang-compiler/f18/pull/9 Tree-same-pre-rewrite: false --- diff --git a/flang/.gitignore b/flang/.gitignore index 4c1751e..b9f53cf 100644 --- a/flang/.gitignore +++ b/flang/.gitignore @@ -4,6 +4,7 @@ tags ./f18 *.o *~ +*# CMakeCache.txt CMakeFiles/* cmake_install.cmake diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 7fcd0a7..3bbe9ed 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES_F18 lib/parser/position.cc lib/parser/preprocessor.cc lib/parser/prescan.cc + lib/parser/provenance.cc lib/parser/source.cc ) add_executable(f18 ${SOURCES_F18}) diff --git a/flang/lib/parser/provenance.cc b/flang/lib/parser/provenance.cc new file mode 100644 index 0000000..4050d9e --- /dev/null +++ b/flang/lib/parser/provenance.cc @@ -0,0 +1,87 @@ +#include "provenance.h" +#include "idioms.h" +#include "position.h" +#include +namespace Fortran { +namespace parser { + +Origin::Origin(const SourceFile &source) : u_{Inclusion{source}} {} +Origin::Origin(const SourceFile &included, ProvenanceRange from) + : u_{Inclusion{included}}, replaces_{from} {} +Origin::Origin(ProvenanceRange def, ProvenanceRange use, + const std::string &expansion) + : u_{Macro{def, expansion}}, replaces_{use} {} + +size_t Origin::size() const { + return std::visit( + visitors{[](const Inclusion &inc) { return inc.source.bytes(); }, + [](const Macro &mac) { return mac.expansion.size(); }}, + u_); +} + +const char &Origin::operator[](size_t n) const { + return std::visit( + visitors{[n](const Inclusion &inc) -> const char & { + return inc.source.content()[n]; }, + [n](const Macro &mac) -> const char & { return mac.expansion[n]; }}, + u_); +} + +void Origin::Identify(std::ostream &o, const AllOfTheSource &sources, size_t at, + const std::string &prefix) const { + static const std::string indented{prefix + " "}; + std::visit( + visitors{ + [&](const Inclusion &inc) { + Position pos{inc.source.FindOffsetPosition(at)}; + o << prefix << "at line " << pos.lineNumber() << ", column " << + pos.column() << "in the file " << inc.source.path() << '\n'; + if (replaces_.bytes() > 0) { + o << prefix << " that was included\n"; + sources.Identify(o, replaces_.start(), indented); + } + }, + [&](const Macro &mac) { + o << prefix << "in the expansion of a macro that was defined\n"; + sources.Identify(o, mac.definition.start(), indented); + o << prefix << "... and called\n"; + sources.Identify(o, replaces_.start(), indented); + o << prefix << "... and expanded to\n" << + indented << mac.expansion << '\n'; }}, + u_); +} + +AllOfTheSource &AllOfTheSource::Add(Origin &&origin) { + size_t start{bytes_}; + bytes_ += origin.size(); + chunk_.emplace_back(Chunk{std::move(origin), start}); + return *this; +} + +const char &AllOfTheSource::operator[](Provenance at) const { + const Chunk &chunk{MapToChunk(at)}; + return chunk.origin[at - chunk.start]; +} + +const AllOfTheSource::Chunk &AllOfTheSource::MapToChunk(Provenance at) const { + CHECK(at < bytes_); + size_t low{0}, count{chunk_.size()}; + while (count > 1) { + size_t mid{low + (count >> 1)}; + if (chunk_[mid].start > at) { + count = mid - low; + } else { + count -= mid - low; + low = mid; + } + } + return chunk_[low]; +} + +void AllOfTheSource::Identify(std::ostream &o, Provenance at, + const std::string &prefix) const { + const Chunk &chunk{MapToChunk(at)}; + return chunk.origin.Identify(o, *this, at - chunk.start, prefix); +} +} // namespace parser +} // namespace Fortran diff --git a/flang/lib/parser/provenance.h b/flang/lib/parser/provenance.h index 7d6a86f..9feb4b7b 100644 --- a/flang/lib/parser/provenance.h +++ b/flang/lib/parser/provenance.h @@ -1,40 +1,67 @@ #ifndef FORTRAN_PROVENANCE_H_ #define FORTRAN_PROVENANCE_H_ #include "source.h" +#include +#include #include #include namespace Fortran { - -class SourceContexts; +namespace parser { using Provenance = size_t; -struct ProvenanceRange { - Provenance begin; - size_t bytes; +class ProvenanceRange { +public: + ProvenanceRange() {} + bool empty() const { return bytes_ == 0; } + Provenance start() const { return start_; } + size_t bytes() const { return bytes_; } +private: + Provenance start_{0}; + size_t bytes_{0}; }; -class Sources { +class AllOfTheSource; + +class Origin { public: - Sources() {} - Sources(Sources &&) = default; - Sources &operator(Sources &&) = default; - size_t size() const { return bytes_; } - char &operator[size_t at] const; + explicit Origin(const SourceFile &); // initial source file + Origin(const SourceFile &, ProvenanceRange); // included source file + Origin(ProvenanceRange def, ProvenanceRange use, // macro call + const std::string &expansion); + size_t size() const; + const char &operator[](size_t) const; + void Identify(std::ostream &, const AllOfTheSource &, size_t, + const std::string &indent) const; private: - struct Context { - struct Inclusion { - const SourceFile &source; - }; - struct MacroUse { - ProvenanceRange definition; - }; + struct Inclusion { + const SourceFile &source; + }; + struct Macro { + ProvenanceRange definition; + std::string expansion; + }; + std::variant u_; + ProvenanceRange replaces_; +}; - int myIndex; // *contexts[myIndex] == this; - ProvenanceRange replaces; - std::variant v; +class AllOfTheSource { +public: + AllOfTheSource() {} + AllOfTheSource(AllOfTheSource &&) = default; + AllOfTheSource &operator=(AllOfTheSource &&) = default; + size_t size() const { return bytes_; } + const char &operator[](Provenance) const; + AllOfTheSource &Add(Origin &&); + void Identify(std::ostream &, Provenance, const std::string &prefix) const; +private: + struct Chunk { + Chunk(Origin &&origin, size_t at) : origin{std::move(origin)}, start{at} {} + Origin origin; + size_t start; }; - std::vector> contexts_; + const Chunk &MapToChunk(Provenance) const; + std::vector chunk_; size_t bytes_; }; @@ -51,11 +78,11 @@ class ProvenancedString { private: class iterator { public: - iterator(const Sources &sources, Provenance at) + iterator(const AllOfTheSource &sources, Provenance at) : sources_{&sources}, at_{at} {} iterator(const iterator &that) : sources_{that.sources_}, at_{that.at_} {} - iterator &operator(const iterator &that) { + iterator &operator=(const iterator &that) { sources_ = that.sources_; at_ = that.at_; return *this; @@ -65,7 +92,7 @@ private: ++at_; return *this; } - iterator &operator++(int) { + iterator operator++(int) { iterator result{*this}; ++at_; return result; @@ -75,14 +102,14 @@ private: bool operator==(const iterator &that) { return at_ == that.at_; } bool operator!=(const iterator &that) { return at_ != that.at_; } private: - const Sources *sources_; + const AllOfTheSource *sources_; size_t at_; }; - iterator begin(const Sources &sources) const { + iterator begin(const AllOfTheSource &sources) const { return iterator(sources, start_); } - iterator end(const Sources &sources) const { + iterator end(const AllOfTheSource &sources) const { return iterator(sources, start_ + bytes_); } public: @@ -91,5 +118,6 @@ private: Provenance start_; size_t bytes_; }; +} // namespace parser } // namespace Fortran #endif // FORTRAN_PROVENANCE_H_ diff --git a/flang/lib/parser/source.cc b/flang/lib/parser/source.cc index ff61130..2b5025e 100644 --- a/flang/lib/parser/source.cc +++ b/flang/lib/parser/source.cc @@ -146,16 +146,21 @@ void SourceFile::Close() { Position SourceFile::FindOffsetPosition(size_t at) const { CHECK(at < bytes_); - size_t lo{0}, hi{lineStart_.size()}; - while (lo < hi) { - size_t mid{(lo + hi) >> 1}; + if (lineStart_.empty()) { + return {1, static_cast(at + 1)}; + } + size_t low{0}, count{lineStart_.size()}; + while (count > 1) { + size_t mid{low + (count >> 1)}; if (lineStart_[mid] > at) { - hi = mid; + count = mid - low; } else { - lo = mid; + count -= mid - low; + low = mid; } } - return {static_cast(lo + 1), static_cast(at - lineStart_[lo] + 1)}; + return {static_cast(low + 1), + static_cast(at - lineStart_[low] + 1)}; } size_t SourceFile::FindPositionOffset(int lineNumber, int column) const {