From 1eb9948f02560912c67757e18d105d18609935ce Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Wed, 15 Mar 2023 17:57:58 -0700 Subject: [PATCH] [flang] Catch more bad DATA statement objects The data statement variable checker is missing some cases, like expressions that are not variables. Run the checker first to enjoy its very specific error messages, but when it finds no problems, still apply a general check that an expression is a "variable" and also not a constant expression at the top level as a backstop. Differential Revision: https://reviews.llvm.org/D146580 --- flang/lib/Semantics/check-data.cpp | 35 +++++++++++++++++++++-------------- flang/test/Semantics/data03.f90 | 10 ++++++---- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp index 955998b..f33258e 100644 --- a/flang/lib/Semantics/check-data.cpp +++ b/flang/lib/Semantics/check-data.cpp @@ -179,24 +179,27 @@ private: bool isFirstSymbol_{true}; }; +static bool IsValidDataObject(const SomeExpr &expr) { // C878, C879 + return !evaluate::IsConstantExpr(expr) && + (evaluate::IsVariable(expr) || evaluate::IsProcedurePointer(expr)); +} + void DataChecker::Leave(const parser::DataIDoObject &object) { if (const auto *designator{ std::get_if>>( &object.u)}) { if (MaybeExpr expr{exprAnalyzer_.Analyze(*designator)}) { auto source{designator->thing.value().source}; - if (evaluate::IsConstantExpr(*expr)) { // C878,C879 - exprAnalyzer_.context().Say( - source, "Data implied do object must be a variable"_err_en_US); - } else { - DataVarChecker checker{exprAnalyzer_.context(), source}; - if (checker(*expr)) { - if (checker.HasComponentWithoutSubscripts()) { // C880 - exprAnalyzer_.context().Say(source, - "Data implied do structure component must be subscripted"_err_en_US); - } else { - return; - } + DataVarChecker checker{exprAnalyzer_.context(), source}; + if (checker(*expr)) { + if (checker.HasComponentWithoutSubscripts()) { // C880 + exprAnalyzer_.context().Say(source, + "Data implied do structure component must be subscripted"_err_en_US); + } else if (!IsValidDataObject(*expr)) { + exprAnalyzer_.context().Say( + source, "Data implied do object must be a variable"_err_en_US); + } else { + return; } } } @@ -211,9 +214,13 @@ void DataChecker::Leave(const parser::DataStmtObject &dataObject) { }, [&](const auto &var) { auto expr{exprAnalyzer_.Analyze(var)}; + auto source{parser::FindSourceLocation(dataObject)}; if (!expr || - !DataVarChecker{exprAnalyzer_.context(), - parser::FindSourceLocation(dataObject)}(*expr)) { + !DataVarChecker{exprAnalyzer_.context(), source}(*expr)) { + currentSetHasFatalErrors_ = true; + } else if (!IsValidDataObject(*expr)) { + exprAnalyzer_.context().Say( + source, "Data statement object must be a variable"_err_en_US); currentSetHasFatalErrors_ = true; } }, diff --git a/flang/test/Semantics/data03.f90 b/flang/test/Semantics/data03.f90 index b3ed338..d9bead7 100644 --- a/flang/test/Semantics/data03.f90 +++ b/flang/test/Semantics/data03.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -!Testing data constraints : C874 - C875, C878 - C881 +!Testing data constraints : C874 - C875, C878 - C881 module m integer, target :: modarray(1) contains @@ -8,7 +8,7 @@ module m integer, pointer :: f f => modarray(i) end - subroutine CheckObject + subroutine CheckObject type specialNumbers integer one integer numbers(5) @@ -34,6 +34,8 @@ module m integer :: d(10, 10) character :: name(12) integer :: ind = 2 + !ERROR: Data statement object must be a variable + DATA name%len / 666 / !C874 !ERROR: Data object must not be a coindexed variable DATA a[1] / 1 / @@ -77,7 +79,7 @@ module m !C881 !ERROR: Data object must have constant subscripts DATA(b(x), i = 1, 5) / 5 * 1 / - !C881 + !C881 !OK: Correct use DATA(nums % numbers(i), i = 1, 5) / 5 * 1 / !C881 @@ -86,5 +88,5 @@ module m !C881 !OK: Correct use DATA(d(i, 1), i = 1, 10) / 10 * 1 / - end + end end -- 2.7.4