Skip to content

Commit

Permalink
[flang] FindOffsetLineAndColumn also uses SourcePosition.
Browse files Browse the repository at this point in the history
New tests for COMMON and BLOCK.
Added CHECK-ONCE to test_any.sh. Make sure pattern only occurs once.

Original-commit: flang-compiler/f18@ad82daf
Reviewed-on: flang-compiler/f18#698
Tree-same-pre-rewrite: false
  • Loading branch information
lahlidahlia committed Sep 11, 2019
1 parent 2f205a5 commit 69fd49a
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 67 deletions.
16 changes: 8 additions & 8 deletions flang/lib/parser/provenance.cc
Expand Up @@ -239,18 +239,18 @@ void AllSources::EmitMessage(std::ostream &o,
[&](const Inclusion &inc) {
o << inc.source.path();
std::size_t offset{origin.covers.MemberOffset(range->start())};
std::pair<int, int> pos{inc.source.FindOffsetLineAndColumn(offset)};
o << ':' << pos.first << ':' << pos.second;
SourcePosition pos{inc.source.FindOffsetLineAndColumn(offset)};
o << ':' << pos.line << ':' << pos.column;
o << ": " << message << '\n';
if (echoSourceLine) {
const char *text{inc.source.content() +
inc.source.GetLineStartOffset(pos.first)};
inc.source.GetLineStartOffset(pos.line)};
o << " ";
for (const char *p{text}; *p != '\n'; ++p) {
o << *p;
}
o << "\n ";
for (int j{1}; j < pos.second; ++j) {
for (int j{1}; j < pos.column; ++j) {
char ch{text[j - 1]};
o << (ch == '\t' ? '\t' : ' ');
}
Expand All @@ -260,8 +260,8 @@ void AllSources::EmitMessage(std::ostream &o,
if (&MapToOrigin(last) == &origin) {
auto endOffset{origin.covers.MemberOffset(last)};
auto endPos{inc.source.FindOffsetLineAndColumn(endOffset)};
if (pos.first == endPos.first) {
for (int j{pos.second}; j < endPos.second; ++j) {
if (pos.line == endPos.line) {
for (int j{pos.column}; j < endPos.column; ++j) {
o << '^';
}
}
Expand Down Expand Up @@ -322,7 +322,7 @@ std::optional<SourcePosition> AllSources::GetSourcePosition(
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};
return inc->source.FindOffsetLineAndColumn(offset);
} else {
return std::nullopt;
}
Expand All @@ -345,7 +345,7 @@ std::string AllSources::GetPath(Provenance at) const {
int AllSources::GetLineNumber(Provenance at) const {
std::size_t offset{0};
const SourceFile *source{GetSourceFile(at, &offset)};
return source ? source->FindOffsetLineAndColumn(offset).first : 0;
return source ? source->FindOffsetLineAndColumn(offset).line : 0;
}

Provenance AllSources::CompilerInsertionProvenance(char ch) {
Expand Down
11 changes: 0 additions & 11 deletions flang/lib/parser/provenance.h
Expand Up @@ -138,17 +138,6 @@ class OffsetToProvenanceMappings {
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 {
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/parser/source.cc
Expand Up @@ -256,10 +256,10 @@ void SourceFile::Close() {
path_.clear();
}

std::pair<int, int> SourceFile::FindOffsetLineAndColumn(std::size_t at) const {
SourcePosition SourceFile::FindOffsetLineAndColumn(std::size_t at) const {
CHECK(at < bytes_);
if (lineStart_.empty()) {
return {1, static_cast<int>(at + 1)};
return {*this, 1, static_cast<int>(at + 1)};
}
std::size_t low{0}, count{lineStart_.size()};
while (count > 1) {
Expand All @@ -271,7 +271,7 @@ std::pair<int, int> SourceFile::FindOffsetLineAndColumn(std::size_t at) const {
low = mid;
}
}
return {
static_cast<int>(low + 1), static_cast<int>(at - lineStart_[low] + 1)};
return {*this, static_cast<int>(low + 1),
static_cast<int>(at - lineStart_[low] + 1)};
}
}
14 changes: 13 additions & 1 deletion flang/lib/parser/source.h
Expand Up @@ -33,6 +33,18 @@ std::string DirectoryName(std::string path);
std::string LocateSourceFile(
std::string name, const std::vector<std::string> &searchPath);

class SourceFile;

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} {}

const SourceFile &file;
int line, column;
};

class SourceFile {
public:
explicit SourceFile(Encoding e) : encoding_{e} {}
Expand All @@ -46,7 +58,7 @@ class SourceFile {
bool Open(std::string path, std::stringstream *error);
bool ReadStandardInput(std::stringstream *error);
void Close();
std::pair<int, int> FindOffsetLineAndColumn(std::size_t) const;
SourcePosition FindOffsetLineAndColumn(std::size_t) const;
std::size_t GetLineStartOffset(int lineNumber) const {
return lineStart_.at(lineNumber - 1);
}
Expand Down
61 changes: 30 additions & 31 deletions flang/lib/semantics/semantics.cc
Expand Up @@ -42,9 +42,21 @@ 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);

static 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);
}
}

// A parse tree visitor that calls Enter/Leave functions from each checker
// class C supplied as template parameters. Enter is called before the node's
// children are visited, Leave is called after. No two checkers may have the
Expand Down Expand Up @@ -219,6 +231,23 @@ void Semantics::DumpSymbols(std::ostream &os) {
DoDumpSymbols(os, context_.globalScope());
}

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 DoDumpSymbols(std::ostream &os, const Scope &scope, int indent) {
PutIndent(os, indent);
os << Scope::EnumToString(scope.kind()) << " scope:";
Expand Down Expand Up @@ -270,36 +299,6 @@ 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 << " ";
Expand Down
4 changes: 4 additions & 0 deletions flang/test/semantics/CMakeLists.txt
Expand Up @@ -248,12 +248,16 @@ set(GETSYMBOLS_TESTS
getsymbols01.f90
getsymbols02-*.f90
getsymbols03-a.f90
getsymbols04.f90
getsymbols05.f90
)

set(GETDEFINITION_TESTS
getdefinition01.f90
getdefinition02.f
getdefinition03-a.f90
getdefinition04.f90
getdefinition05.f90
)

set(F18 $<TARGET_FILE:f18>)
Expand Down
25 changes: 25 additions & 0 deletions flang/test/semantics/getdefinition04.f90
@@ -0,0 +1,25 @@
! 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 COMMON block with same name as variable.

program main
integer :: x
integer :: y
common /x/ y
x = y
end program

! RUN: ${F18} -fget-definition 21 3 4 -fparse-only -fdebug-semantics %s | ${FileCheck} %s
! CHECK:x:.*getdefinition04.f90, 18, 14-15
35 changes: 35 additions & 0 deletions flang/test/semantics/getdefinition05.f90
@@ -0,0 +1,35 @@
! 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 BLOCK that contains same variable name as
! another in an outer scope.

program main
integer :: x
integer :: y
block
integer :: x
integer :: y
x = y
end block
x = y
end program

!! Inner x
! RUN: ${F18} -fget-definition 24 5 6 -fparse-only -fdebug-semantics %s > %t;
! CHECK:x:.*getdefinition05.f90, 22, 16-17
!! Outer y
! RUN: ${F18} -fget-definition 26 7 8 -fparse-only -fdebug-semantics %s >> %t;
! CHECK:y:.*getdefinition05.f90, 20, 14-15
! RUN: cat %t | ${FileCheck} %s;
14 changes: 7 additions & 7 deletions flang/test/semantics/getsymbols01.f90
Expand Up @@ -43,10 +43,10 @@ recursive pure function f() result(x)
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
! CHECK-ONCE:m:.*getsymbols01.f90, 18, 8-9
! CHECK-ONCE:f:.*getsymbols01.f90, 37, 26-27
! CHECK-ONCE:s:.*getsymbols01.f90, 25, 18-19
! CHECK-ONCE:ss:.*getsymbols01.f90, 32, 19-21
! CHECK-ONCE:x:.*getsymbols01.f90, 25, 21-22
! CHECK-ONCE:y:.*getsymbols01.f90, 25, 24-25
! CHECK-ONCE:x:.*getsymbols01.f90, 39, 24-25
27 changes: 27 additions & 0 deletions flang/test/semantics/getsymbols04.f90
@@ -0,0 +1,27 @@
! 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 COMMON.

program main
integer :: x
integer :: y
common /x/ y
x = y
end program

! RUN: ${F18} -fget-symbols-sources -fparse-only -fdebug-semantics %s 2>&1 | ${FileCheck} %s
! CHECK:x:.*getsymbols04.f90, 18, 14-15
! CHECK:y:.*getsymbols04.f90, 19, 14-15
! CHECK:x:.*getsymbols04.f90, 20, 11-12
30 changes: 30 additions & 0 deletions flang/test/semantics/getsymbols05.f90
@@ -0,0 +1,30 @@
! 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 COMMON.

program main
integer :: x
integer :: y
block
integer :: x
x = y
end block
x = y
end program

! RUN: ${F18} -fget-symbols-sources -fparse-only -fdebug-semantics %s 2>&1 | ${FileCheck} %s
! CHECK:x:.*getsymbols05.f90, 18, 14-15
! CHECK:y:.*getsymbols05.f90, 19, 14-15
! CHECK:x:.*getsymbols05.f90, 21, 16-17
13 changes: 13 additions & 0 deletions flang/test/semantics/test_any.sh
Expand Up @@ -45,6 +45,18 @@ function internal_check() {
r=false
fi
done < ${lcheck}
egrep '^[[:space:]]*![[:space:]]*CHECK-ONCE:[[:space:]]*' ${linput} | sed -e 's/^[[:space:]]*![[:space:]]*CHECK-ONCE:[[:space:]]*//' > ${lcheck} 2>/dev/null
while read p; do
count=$(egrep -o -e "${p}" ${lstdin} | wc -l)
if [ ${count} -eq 0 ]; then
echo "Not found: ${p}" >&2
r=false
fi
if [ ${count} -gt 1 ]; then
echo "Found duplicates: ${p}" >&2
r=false
fi
done < ${lcheck}
rm -f ${lstdin} ${lcheck}
${r}
}
Expand All @@ -55,6 +67,7 @@ for input in ${srcdir}/$*; do
CMD=$(echo ${CMD} | sed -e "s:%s:${input}:g")
if egrep -q -e '%t' <<< ${CMD} ; then
temp=`mktemp`
trap "rm -f ${temp}" EXIT
CMD=$(echo ${CMD} | sed -e "s:%t:${temp}:g")
fi
if $(eval $CMD); then
Expand Down

0 comments on commit 69fd49a

Please sign in to comment.