Skip to content

Commit

Permalink
[flang]Implemented Semantic Checkes for 5 data constraints
Browse files Browse the repository at this point in the history
Summary:
 C874, C875, C878, C880 and C881 checks are implemented.

Differential Revision: https://reviews.llvm.org/D78008
  • Loading branch information
anchuraj committed Apr 18, 2020
1 parent 0d3149f commit c1c0121
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 2 deletions.
91 changes: 89 additions & 2 deletions flang/lib/Semantics/check-data.cpp
Expand Up @@ -10,6 +10,59 @@

namespace Fortran::semantics {

template <typename T> void DataChecker::CheckIfConstantSubscript(const T &x) {
evaluate::ExpressionAnalyzer exprAnalyzer{context_};
if (MaybeExpr checked{exprAnalyzer.Analyze(x)}) {
if (!evaluate::IsConstantExpr(*checked)) { // C875,C881
context_.Say(parser::FindSourceLocation(x),
"Data object must have constant bounds"_err_en_US);
}
}
}

void DataChecker::CheckSubscript(const parser::SectionSubscript &subscript) {
std::visit(common::visitors{
[&](const parser::SubscriptTriplet &triplet) {
CheckIfConstantSubscript(std::get<0>(triplet.t));
CheckIfConstantSubscript(std::get<1>(triplet.t));
CheckIfConstantSubscript(std::get<2>(triplet.t));
},
[&](const parser::IntExpr &intExpr) {
CheckIfConstantSubscript(intExpr);
},
},
subscript.u);
}

// Returns false if DataRef has no subscript
bool DataChecker::CheckAllSubscriptsInDataRef(
const parser::DataRef &dataRef, parser::CharBlock source) {
return std::visit(
common::visitors{
[&](const parser::Name &) { return false; },
[&](const common::Indirection<parser::StructureComponent>
&structureComp) {
return CheckAllSubscriptsInDataRef(
structureComp.value().base, source);
},
[&](const common::Indirection<parser::ArrayElement> &arrayElem) {
for (auto &subscript : arrayElem.value().subscripts) {
CheckSubscript(subscript);
}
CheckAllSubscriptsInDataRef(arrayElem.value().base, source);
return true;
},
[&](const common::Indirection<parser::CoindexedNamedObject>
&coindexedObj) { // C874
context_.Say(source,
"Data object must not be a coindexed variable"_err_en_US);
CheckAllSubscriptsInDataRef(coindexedObj.value().base, source);
return true;
},
},
dataRef.u);
}

void DataChecker::Leave(const parser::DataStmtConstant &dataConst) {
if (auto *structure{
std::get_if<parser::StructureConstructor>(&dataConst.u)}) {
Expand All @@ -25,10 +78,44 @@ void DataChecker::Leave(const parser::DataStmtConstant &dataConst) {
}
}
}
// TODO: C886 and C887 for data-stmt-constant
}

// TODO: C874-C881
// TODO: C876, C877, C879
void DataChecker::Leave(const parser::DataImpliedDo &dataImpliedDo) {
for (const auto &object :
std::get<std::list<parser::DataIDoObject>>(dataImpliedDo.t)) {
if (const auto *designator{parser::Unwrap<parser::Designator>(object)}) {
if (auto *dataRef{std::get_if<parser::DataRef>(&designator->u)}) {
evaluate::ExpressionAnalyzer exprAnalyzer{context_};
if (MaybeExpr checked{exprAnalyzer.Analyze(*dataRef)}) {
if (evaluate::IsConstantExpr(*checked)) { // C878
context_.Say(designator->source,
"Data implied do object must be a variable"_err_en_US);
}
}
if (!CheckAllSubscriptsInDataRef(*dataRef,
designator->source)) { // C880
context_.Say(designator->source,
"Data implied do object must be subscripted"_err_en_US);
}
}
}
}
}

void DataChecker::Leave(const parser::DataStmtObject &dataObject) {
if (std::get_if<common::Indirection<parser::Variable>>(&dataObject.u)) {
if (const auto *designator{
parser::Unwrap<parser::Designator>(dataObject)}) {
if (auto *dataRef{std::get_if<parser::DataRef>(&designator->u)}) {
CheckAllSubscriptsInDataRef(*dataRef, designator->source);
}
} else { // C875
context_.Say(parser::FindSourceLocation(dataObject),
"Data object variable must not be a function reference"_err_en_US);
}
}
}

void DataChecker::Leave(const parser::DataStmtRepeat &dataRepeat) {
if (const auto *designator{parser::Unwrap<parser::Designator>(dataRepeat)}) {
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Semantics/check-data.h
Expand Up @@ -20,9 +20,14 @@ class DataChecker : public virtual BaseChecker {
DataChecker(SemanticsContext &context) : context_{context} {}
void Leave(const parser::DataStmtRepeat &);
void Leave(const parser::DataStmtConstant &);
void Leave(const parser::DataStmtObject &);
void Leave(const parser::DataImpliedDo &);

private:
SemanticsContext &context_;
template <typename T> void CheckIfConstantSubscript(const T &);
void CheckSubscript(const parser::SectionSubscript &);
bool CheckAllSubscriptsInDataRef(const parser::DataRef &, parser::CharBlock);
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CHECK_DATA_H_
83 changes: 83 additions & 0 deletions flang/test/Semantics/data03.f90
@@ -0,0 +1,83 @@
! RUN: %B/test/Semantics/test_errors.sh %s %flang %t
!Testing data constraints : C874 - C875, C878 - C881
module m
contains
function f(i)
integer ::i
integer ::result
result = i *1024
end
subroutine CheckObject
type specialNumbers
integer one
integer numbers(5)
end type
type large
integer elt(10)
integer val
type(specialNumbers) nums
type(specialNumbers) numsArray(5)
end type
type(specialNumbers), parameter ::newNums = &
specialNumbers(1, (/ 1, 2, 3, 4, 5 /))
type(specialNumbers), parameter ::newNumsArray(2) = &
(/ SpecialNumbers(1, (/ 1, 2, 3, 4, 5 /)), &
SpecialNumbers(1, (/ 1, 2, 3,4, 5 /)) /)
type(specialNumbers) nums
type(large) largeArray(5)
type(large) largeNumber
real :: a[*]
real :: b(5)
integer :: x
real, parameter:: c(5) = (/ 1, 2, 3, 4, 5 /)
integer :: d(10, 10)
character :: name(12)
integer :: ind = 2
!C874
!ERROR: Data object must not be a coindexed variable
DATA a[1] / 1 /
!C874
!ERROR: Data object must not be a coindexed variable
DATA(a[i], i = 1, 5) / 5 * 1 /
!C875
!ERROR: Data object variable must not be a function reference
DATA f(1) / 1 /
!C875
!ERROR: Data object must have constant bounds
DATA b(ind) / 1 /
!C875
!ERROR: Data object must have constant bounds
DATA name( : ind) / 'Ancd' /
!C875
!ERROR: Data object must have constant bounds
DATA name(ind:) / 'Ancd' /
!C878
!ERROR: Data implied do object must be a variable
DATA(c(i), i = 1, 5) / 5 * 1 /
!C878
!ERROR: Data implied do object must be a variable
DATA(newNumsArray(i), i = 1, 2) &
/ specialNumbers(1, 2 * (/ 1, 2, 3, 4, 5 /)) /
!C880
!ERROR: Data implied do object must be subscripted
DATA(nums % one, i = 1, 5) / 5 * 1 /
!C880
!OK: Correct use
DATA(largeArray(j) % nums % one, j = 1, 10) / 10 * 1 /
!C880
!OK: Correct use
DATA(largeNumber % numsArray(j) % one, j = 1, 10) / 10 * 1 /
!C881
!ERROR: Data object must have constant bounds
DATA(b(x), i = 1, 5) / 5 * 1 /
!C881
!OK: Correct use
DATA(nums % numbers(i), i = 1, 5) / 5 * 1 /
!C881
!OK: Correct use
DATA((d(i, j), i = 1, 10), j = 1, 10) / 100 * 1 /
!C881
!OK: Correct use
DATA(d(i, 1), i = 1, 10) / 10 * 1 /
end
end

0 comments on commit c1c0121

Please sign in to comment.