[flang-commits] [flang] c1c0121 - [flang]Implemented Semantic Checkes for 5 data constraints
Anchu Rajendran via flang-commits
flang-commits at lists.llvm.org
Fri Apr 17 23:56:51 PDT 2020
Author: Anchu Rajendran
Date: 2020-04-18T12:21:30+05:30
New Revision: c1c01212c49a0792c0594662db84be271e29cba6
URL: https://github.com/llvm/llvm-project/commit/c1c01212c49a0792c0594662db84be271e29cba6
DIFF: https://github.com/llvm/llvm-project/commit/c1c01212c49a0792c0594662db84be271e29cba6.diff
LOG: [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
Added:
flang/test/Semantics/data03.f90
Modified:
flang/lib/Semantics/check-data.cpp
flang/lib/Semantics/check-data.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp
index 6178eb7360ca..c1cc880583de 100644
--- a/flang/lib/Semantics/check-data.cpp
+++ b/flang/lib/Semantics/check-data.cpp
@@ -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)}) {
diff --git a/flang/lib/Semantics/check-data.h b/flang/lib/Semantics/check-data.h
index 5d66c8e74e55..6624574fe921 100644
--- a/flang/lib/Semantics/check-data.h
+++ b/flang/lib/Semantics/check-data.h
@@ -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_
diff --git a/flang/test/Semantics/data03.f90 b/flang/test/Semantics/data03.f90
new file mode 100644
index 000000000000..6548c047e438
--- /dev/null
+++ b/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
More information about the flang-commits
mailing list