forked from OSchip/llvm-project
[flang]Implemented Semantic Checkes for 5 data constraints
Summary: C874, C875, C878, C880 and C881 checks are implemented. Differential Revision: https://reviews.llvm.org/D78008
This commit is contained in:
parent
0d3149f431
commit
c1c01212c4
|
@ -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)}) {
|
||||
|
@ -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)}) {
|
||||
|
|
|
@ -20,9 +20,14 @@ public:
|
|||
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_
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue