diff options
author | Peter Klausler <pklausler@nvidia.com> | 2023-03-15 17:57:58 -0700 |
---|---|---|
committer | Peter Klausler <pklausler@nvidia.com> | 2023-03-27 16:10:03 -0700 |
commit | 1eb9948f02560912c67757e18d105d18609935ce (patch) | |
tree | 40312ae880afae73565c88242be2332a1f853595 /flang/lib | |
parent | da18ceb4b1d54829f73ae4373b59f6ed30314115 (diff) | |
download | llvm-1eb9948f02560912c67757e18d105d18609935ce.tar.gz |
[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
Diffstat (limited to 'flang/lib')
-rw-r--r-- | flang/lib/Semantics/check-data.cpp | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp index 955998bedc0c..f33258ea7c19 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<parser::Scalar<common::Indirection<parser::Designator>>>( &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; } }, |