[flang] Added -fget-definitions and -fget-all-symbols.

- -fget-definitions finds the definition of the symbol under specified source
position.
- -fget-all-symbols finds definition locations of all symbols in a document. For
symbols found in other modules, shows which module the symbol came from.
- Tests.
- New structure SourcePosition with file, line, column information.

Original-commit: flang-compiler/f18@e0099b0900
Reviewed-on: https://github.com/flang-compiler/f18/pull/698
Tree-same-pre-rewrite: false
This commit is contained in:
Tin Huynh 2019-08-26 15:16:57 -07:00
parent 99fb2cfc2f
commit 2f205a5f52
17 changed files with 532 additions and 4 deletions

View File

@ -111,6 +111,17 @@ ProvenanceRange OffsetToProvenanceMappings::Map(std::size_t at) const {
return provenanceMap_[low].range.Suffix(offset);
}
std::optional<std::size_t> OffsetToProvenanceMappings::ReverseMap(
Provenance at) const {
for (const auto &[start, range] : provenanceMap_) {
if (range.Contains(at)) {
std::size_t offset{at.offset() - range.start().offset()};
return start + offset;
}
}
return std::nullopt;
}
void OffsetToProvenanceMappings::RemoveLastBytes(std::size_t bytes) {
for (; bytes > 0; provenanceMap_.pop_back()) {
CHECK(!provenanceMap_.empty());
@ -306,6 +317,26 @@ const SourceFile *AllSources::GetSourceFile(
origin.u);
}
std::optional<SourcePosition> AllSources::GetSourcePosition(
Provenance prov) const {
const Origin &origin{MapToOrigin(prov)};
if (const auto *inc{std::get_if<Inclusion>(&origin.u)}) {
std::size_t offset{origin.covers.MemberOffset(prov)};
return SourcePosition{inc->source, offset};
} else {
return std::nullopt;
}
}
std::optional<ProvenanceRange> AllSources::GetFirstFileProvenance() const {
for (const auto &origin : origin_) {
if (std::holds_alternative<Inclusion>(origin.u)) {
return origin.covers;
}
}
return std::nullopt;
}
std::string AllSources::GetPath(Provenance at) const {
const SourceFile *source{GetSourceFile(at)};
return source ? source->path() : ""s;
@ -412,6 +443,42 @@ std::optional<CharBlock> CookedSource::GetCharBlock(
}
}
std::optional<CharBlock> CookedSource::GetCharBlockFromLineAndColumns(
int line, int startColumn, int endColumn) const {
// 2nd column is exclusive, meaning it is target column + 1.
CHECK(line > 0 && startColumn > 0 && endColumn > 0);
auto provenanceStart{allSources_.GetFirstFileProvenance().value().start()};
if (auto sourceFile{allSources_.GetSourceFile(provenanceStart)}) {
CHECK(line <= static_cast<int>(sourceFile->lines()));
if (auto firstOffset{
provenanceMap_.ReverseMap(sourceFile->GetLineStartOffset(line) +
provenanceStart.offset() + startColumn - 1)}) {
if (auto secondOffset{
provenanceMap_.ReverseMap(sourceFile->GetLineStartOffset(line) +
provenanceStart.offset() + endColumn - 2)}) {
if (*secondOffset >= *firstOffset) {
// Returned 2nd column is also exclusive.
return CharBlock(
&data_[*firstOffset], *secondOffset - *firstOffset + 1);
}
}
}
}
}
std::optional<std::pair<SourcePosition, SourcePosition>>
CookedSource::GetSourcePositionRange(CharBlock cookedRange) const {
if (auto range{GetProvenanceRange(cookedRange)}) {
if (auto firstOffset{allSources_.GetSourcePosition(range->start())}) {
if (auto secondOffset{
allSources_.GetSourcePosition(range->start() + range->size())}) {
return std::pair{*firstOffset, *secondOffset};
}
}
}
return std::nullopt;
}
void CookedSource::Marshal() {
CHECK(provenanceMap_.SizeInBytes() == buffer_.bytes());
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));

View File

@ -52,8 +52,6 @@ namespace Fortran::parser {
// by the upper bits of an offset, but that does not appear to be
// necessary.)
class AllSources;
class Provenance {
public:
Provenance() {}
@ -124,6 +122,7 @@ public:
void Put(ProvenanceRange);
void Put(const OffsetToProvenanceMappings &);
ProvenanceRange Map(std::size_t at) const;
std::optional<std::size_t> ReverseMap(Provenance) const;
void RemoveLastBytes(std::size_t);
ProvenanceRangeToOffsetMappings Invert(const AllSources &) const;
std::ostream &Dump(std::ostream &) const;
@ -139,6 +138,17 @@ private:
std::vector<ContiguousProvenanceMapping> provenanceMap_;
};
struct SourcePosition {
SourcePosition(const SourceFile &file, int line, int column)
: file{file}, line{line}, column{column} {}
SourcePosition(const SourceFile &file, std::pair<int, int> pos)
: file{file}, line{pos.first}, column{pos.second} {}
SourcePosition(const SourceFile &, std::size_t);
const SourceFile &file;
int line, column;
};
// A singleton AllSources instance for the whole compilation
// is shared by reference.
class AllSources {
@ -173,6 +183,8 @@ public:
const std::string &message, bool echoSourceLine = false) const;
const SourceFile *GetSourceFile(
Provenance, std::size_t *offset = nullptr) const;
std::optional<SourcePosition> GetSourcePosition(Provenance) const;
std::optional<ProvenanceRange> GetFirstFileProvenance();
std::string GetPath(Provenance) const; // __FILE__
int GetLineNumber(Provenance) const; // __LINE__
Provenance CompilerInsertionProvenance(char ch);
@ -237,6 +249,10 @@ public:
std::optional<ProvenanceRange> GetProvenanceRange(CharBlock) const;
std::optional<CharBlock> GetCharBlock(ProvenanceRange) const;
std::optional<CharBlock> GetCharBlockFromLineAndColumns(
int line, int startColumn, int endColumn) const;
std::optional<std::pair<SourcePosition, SourcePosition>>
GetSourcePositionRange(CharBlock) const;
// The result of a Put() is the offset that the new data
// will have in the eventually marshaled contiguous buffer.

View File

@ -40,7 +40,9 @@
namespace Fortran::semantics {
using NameToSymbolMap = std::map<const char *, const Symbol *>;
static void DoDumpSymbols(std::ostream &, const Scope &, int indent = 0);
static void GetSymbolNames(const Scope &, NameToSymbolMap &);
static void PutIndent(std::ostream &, int indent);
// A parse tree visitor that calls Enter/Leave functions from each checker
@ -268,6 +270,36 @@ void DoDumpSymbols(std::ostream &os, const Scope &scope, int indent) {
--indent;
}
void Semantics::DumpSymbolsSources(std::ostream &os) const {
NameToSymbolMap symbols;
GetSymbolNames(context_.globalScope(), symbols);
for (const auto pair : symbols) {
const Symbol &symbol{*pair.second};
auto sourceInfo{cooked_.GetSourcePositionRange(symbol.name())};
if (sourceInfo) {
os << symbol.name().ToString() << ": " << sourceInfo->first.file.path()
<< ", " << sourceInfo->first.line << ", " << sourceInfo->first.column
<< "-" << sourceInfo->second.column << "\n";
} else if (symbol.has<semantics::UseDetails>()) {
os << symbol.name().ToString() << ": "
<< symbol.GetUltimate().owner().symbol()->name().ToString() << "\n";
}
}
}
void GetSymbolNames(const Scope &scope, NameToSymbolMap &symbols) {
// Finds all symbol names in the scope without collecting duplicates.
for (const auto &pair : scope) {
symbols.emplace(pair.second->name().begin(), pair.second);
}
for (const auto &pair : scope.commonBlocks()) {
symbols.emplace(pair.second->name().begin(), pair.second);
}
for (const auto &child : scope.children()) {
GetSymbolNames(child, symbols);
}
}
static void PutIndent(std::ostream &os, int indent) {
for (int i = 0; i < indent; ++i) {
os << " ";

View File

@ -181,6 +181,7 @@ public:
bool AnyFatalError() const { return context_.AnyFatalError(); }
void EmitMessages(std::ostream &) const;
void DumpSymbols(std::ostream &);
void DumpSymbolsSources(std::ostream &) const;
private:
SemanticsContext &context_;

View File

@ -244,6 +244,18 @@ set(FORALL_TESTS
forall*.[Ff]90
)
set(GETSYMBOLS_TESTS
getsymbols01.f90
getsymbols02-*.f90
getsymbols03-a.f90
)
set(GETDEFINITION_TESTS
getdefinition01.f90
getdefinition02.f
getdefinition03-a.f90
)
set(F18 $<TARGET_FILE:f18>)
foreach(test ${ERROR_TESTS})
@ -261,7 +273,8 @@ foreach(test ${MODFILE_TESTS})
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_modfile.sh ${test} ${F18})
endforeach()
foreach(test ${LABEL_TESTS} ${CANONDO_TESTS} ${DOCONCURRENT_TESTS} ${FORALL_TESTS})
foreach(test ${LABEL_TESTS} ${CANONDO_TESTS} ${DOCONCURRENT_TESTS}
${FORALL_TESTS} ${GETSYMBOLS_TESTS} ${GETDEFINITION_TESTS})
add_test(NAME ${test}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_any.sh ${test} ${F18})
endforeach()

View File

@ -0,0 +1,54 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-definition returning source position of symbol definition.
!DEF: /m Module
module m
!DEF: /m/f PRIVATE, PURE, RECURSIVE Subprogram REAL(4)
private :: f
contains
!DEF: /m/s BIND(C), PUBLIC, PURE Subprogram
!DEF: /m/s/x INTENT(IN) (implicit) ObjectEntity REAL(4)
!DEF: /m/s/y INTENT(INOUT) (implicit) ObjectEntity REAL(4)
pure subroutine s (x, yyy) bind(c)
!REF: /m/s/x
intent(in) :: x
!REF: /m/s/y
intent(inout) :: yyy
contains
!DEF: /m/s/ss PURE Subprogram
pure subroutine ss
end subroutine
end subroutine
!REF: /m/f
!DEF: /m/f/x ALLOCATABLE ObjectEntity REAL(4)
recursive pure function f() result(x)
!REF: /m/f/x
real, allocatable :: x
!REF: /m/f/x
x = 1.0
end function
end module
! RUN: echo %t 1>&2;
! RUN: ${F18} -fget-definition 27 17 18 -fparse-only -fdebug-semantics %s > %t;
! RUN: ${F18} -fget-definition 29 20 23 -fparse-only -fdebug-semantics %s >> %t;
! RUN: ${F18} -fget-definition 41 3 4 -fparse-only -fdebug-semantics %s >> %t;
! RUN: ${F18} -fget-definition -fparse-only -fdebug-semantics %s >> %t 2>&1;
! RUN: cat %t | ${FileCheck} %s
! CHECK:x:.*getdefinition01.f90, 25, 21-22
! CHECK:yyy:.*getdefinition01.f90, 25, 24-27
! CHECK:x:.*getdefinition01.f90, 39, 24-25
! CHECK:Invalid argument to -fget-definitions

View File

@ -0,0 +1,52 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-definition with fixed form.
!DEF: /m Module
module m
!DEF: /m/f PRIVATE, PURE, RECURSIVE Subprogram REAL(4)
private :: f
contains
!DEF: /m/s BIND(C), PUBLIC, PURE Subprogram
!DEF: /m/s/x INTENT(IN) (implicit) ObjectEntity REAL(4)
!DEF: /m/s/y INTENT(INOUT) (implicit) ObjectEntity REAL(4)
pure subroutine s (x, yyy) bind(c)
!REF: /m/s/x
intent(in) ::
* x
!REF: /m/s/y
intent(inout) :: yyy
contains
!DEF: /m/s/ss PURE Subprogram
pure subroutine ss
end subroutine
end subroutine
!REF: /m/f
!DEF: /m/f/x ALLOCATABLE ObjectEntity REAL(4)
recursive pure function f() result(x)
!REF: /m/f/x
real, allocatable :: x
!REF: /m/f/x
x = 1.0
end function
end module
! RUN: ${F18} -fget-definition 28 9 10 -fparse-only -fdebug-semantics %s > %t;
! RUN: ${F18} -fget-definition 30 26 29 -fparse-only -fdebug-semantics %s >> %t;
! RUN: ${F18} -fget-definition 42 9 10 -fparse-only -fdebug-semantics %s >> %t;
! RUN: cat %t | ${FileCheck} %s
! CHECK:x:.*getdefinition02.f, 25, 27-28
! CHECK:yyy:.*getdefinition02.f, 25, 30-33
! CHECK:x:.*getdefinition02.f, 40, 30-31

View File

@ -0,0 +1,29 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-definition with INCLUDE
INCLUDE "getdefinition03-b.f90"
program main
use m
integer :: x
x = f
end program
! RUN: ${F18} -fget-definition 22 6 7 -fparse-only -fdebug-semantics %s > %t;
! RUN: ${F18} -fget-definition 22 2 3 -fparse-only -fdebug-semantics %s >> %t;
! RUN: cat %t | ${FileCheck} %s;
! CHECK:f:.*getdefinition03-b.f90, 16, 12-13
! CHECK:x:.*getdefinition03-a.f90, 21, 13-14

View File

@ -0,0 +1,17 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
module m
public :: f
end module

View File

@ -0,0 +1,52 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-symbols-sources finding all symbols in file.
!DEF: /m Module
module m
!DEF: /m/f PRIVATE, PURE, RECURSIVE Subprogram REAL(4)
private :: f
contains
!DEF: /m/s BIND(C), PUBLIC, PURE Subprogram
!DEF: /m/s/x INTENT(IN) (implicit) ObjectEntity REAL(4)
!DEF: /m/s/y INTENT(INOUT) (implicit) ObjectEntity REAL(4)
pure subroutine s (x, y) bind(c)
!REF: /m/s/x
intent(in) :: x
!REF: /m/s/y
intent(inout) :: y
contains
!DEF: /m/s/ss PURE Subprogram
pure subroutine ss
end subroutine
end subroutine
!REF: /m/f
!DEF: /m/f/x ALLOCATABLE ObjectEntity REAL(4)
recursive pure function f() result(x)
!REF: /m/f/x
real, allocatable :: x
!REF: /m/f/x
x = 1.0
end function
end module
! RUN: ${F18} -fget-symbols-sources -fparse-only -fdebug-semantics %s 2>&1 | ${FileCheck} %s
! CHECK:m:.*getsymbols01.f90, 18, 8-9
! CHECK:f:.*getsymbols01.f90, 37, 26-27
! CHECK:s:.*getsymbols01.f90, 25, 18-19
! CHECK:ss:.*getsymbols01.f90, 32, 19-21
! CHECK:x:.*getsymbols01.f90, 25, 21-22
! CHECK:y:.*getsymbols01.f90, 25, 24-25
! CHECK:x:.*getsymbols01.f90, 39, 24-25

View File

@ -0,0 +1,26 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! RUN: ${F18} -fparse-only -fdebug-semantics %s
module m2
implicit none
private
public :: get5
contains
function get5() result(ret)
integer :: ret
ret = 5
end function get5
end module m2

View File

@ -0,0 +1,28 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! RUN: ${F18} -fparse-only -fdebug-semantics %s
module m1
use m2
implicit none
private
public :: callget5
contains
function callget5() result(ret)
implicit none
INTEGER :: ret
ret = get5()
end function callget5
end module m1

View File

@ -0,0 +1,26 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-symbols-sources with modules.
PROGRAM helloworld
use m1
implicit none
integer::i
i = callget5()
ENDPROGRAM
! RUN: ${F18} -fget-symbols-sources -fparse-only -fdebug-semantics %s 2>&1 | ${FileCheck} %s
! CHECK:callget5: m1
! CHECK:get5: m2

View File

@ -0,0 +1,29 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
! Tests -fget-symbols with INCLUDE
INCLUDE "getsymbols03-b.f90"
program main
use m
integer :: x
x = f
end program
! RUN: ${F18} -fget-symbols-sources -fparse-only -fdebug-semantics %s 2>&1 | ${FileCheck} %s
! CHECK:m:.*getsymbols03-b.f90, 15, 8-9
! CHECK:f:.*getsymbols03-b.f90, 16, 12-13
! CHECK:main:.*getsymbols03-a.f90, 19, 9-13
! CHECK:x:.*getsymbols03-a.f90, 21, 13-14

View File

@ -0,0 +1,17 @@
! 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.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
module m
public :: f
end module

View File

@ -53,6 +53,10 @@ gr=0
for input in ${srcdir}/$*; do
CMD=$(cat ${input} | egrep '^[[:space:]]*![[:space:]]*RUN:[[:space:]]*' | sed -e 's/^[[:space:]]*![[:space:]]*RUN:[[:space:]]*//')
CMD=$(echo ${CMD} | sed -e "s:%s:${input}:g")
if egrep -q -e '%t' <<< ${CMD} ; then
temp=`mktemp`
CMD=$(echo ${CMD} | sed -e "s:%t:${temp}:g")
fi
if $(eval $CMD); then
echo "PASS ${input}"
else

View File

@ -101,6 +101,9 @@ struct DriverOptions {
bool unparseTypedExprsToPGF90{false};
std::vector<std::string> pgf90Args;
const char *prefix{nullptr};
bool getDefinition{false};
int getDefinitionArgs[3]; // line, startColumn, endColumn.
bool getSymbolsSources{false};
};
bool ParentProcess() {
@ -226,7 +229,8 @@ std::string CompileFortran(std::string path, Fortran::parser::Options options,
}
// TODO: Change this predicate to just "if (!driver.debugNoSemantics)"
if (driver.debugSemantics || driver.debugResolveNames || driver.dumpSymbols ||
driver.dumpUnparseWithSymbols) {
driver.dumpUnparseWithSymbols || driver.getDefinition ||
driver.getSymbolsSources) {
Fortran::semantics::Semantics semantics{
semanticsContext, parseTree, parsing.cooked()};
semantics.Perform();
@ -247,6 +251,45 @@ std::string CompileFortran(std::string path, Fortran::parser::Options options,
std::cout, parseTree, driver.encoding);
return {};
}
if (driver.getSymbolsSources) {
semantics.DumpSymbolsSources(std::cout);
return {};
}
if (driver.getDefinition) {
std::string notFoundText{"Symbol not found.\n"};
auto cb{parsing.cooked().GetCharBlockFromLineAndColumns(
driver.getDefinitionArgs[0], driver.getDefinitionArgs[1],
driver.getDefinitionArgs[2])};
if (!cb) {
std::cerr << notFoundText;
exitStatus = EXIT_FAILURE;
return {};
}
std::cerr << "String range: >" << std::string(cb->begin(), cb->size())
<< "<\n";
auto &scope{semanticsContext.FindScope(*cb)};
auto symbol{scope.FindSymbol(*cb)};
if (!symbol) {
std::cerr << notFoundText;
exitStatus = EXIT_FAILURE;
return {};
}
std::cerr << "Found symbol name: "
<< std::string(symbol->name().begin(), symbol->name().size())
<< "\n";
auto sourceInfo{parsing.cooked().GetSourcePositionRange(symbol->name())};
if (!sourceInfo) {
std::cerr << notFoundText;
exitStatus = EXIT_FAILURE;
return {};
}
std::cout << symbol->name().ToString() << ": "
<< sourceInfo->first.file.path() << ", "
<< sourceInfo->first.line << ", " << sourceInfo->first.column
<< "-" << sourceInfo->second.column << "\n";
exitStatus = EXIT_SUCCESS;
return {};
}
}
if (driver.dumpParseTree) {
Fortran::parser::DumpTree(std::cout, parseTree);
@ -479,6 +522,26 @@ int main(int argc, char *const argv[]) {
driver.encoding = Fortran::parser::Encoding::UTF_8;
} else if (arg == "-flatin") {
driver.encoding = Fortran::parser::Encoding::LATIN_1;
} else if (arg == "-fget-definition") {
// Receives 3 arguments: line, startColumn, endColumn.
driver.getDefinition = true;
char *endptr;
for (int i = 0; i < 3; i++) {
if (args.empty()) {
std::cerr << "Must provide 3 arguments for -fget-definitions.\n";
return EXIT_FAILURE;
}
driver.getDefinitionArgs[i] =
std::strtol(args.front().c_str(), &endptr, 10);
if (*endptr != '\0') {
std::cerr << "Invalid argument to -fget-definitions: " << args.front()
<< '\n';
return EXIT_FAILURE;
}
args.pop_front();
}
} else if (arg == "-fget-symbols-sources") {
driver.getSymbolsSources = true;
} else if (arg == "-help" || arg == "--help" || arg == "-?") {
std::cerr
<< "f18 options:\n"
@ -506,6 +569,8 @@ int main(int argc, char *const argv[]) {
<< " -fdebug-resolve-names\n"
<< " -fdebug-instrumented-parse\n"
<< " -fdebug-semantics perform semantic checks\n"
<< " -fget-definition\n"
<< " -fget-symbols-sources\n"
<< " -v -c -o -I -D -U have their usual meanings\n"
<< " -help print this again\n"
<< "Other options are passed through to the compiler.\n";