summaryrefslogtreecommitdiff
path: root/flang/lib
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2023-03-15 17:57:58 -0700
committerPeter Klausler <pklausler@nvidia.com>2023-03-27 16:10:03 -0700
commit1eb9948f02560912c67757e18d105d18609935ce (patch)
tree40312ae880afae73565c88242be2332a1f853595 /flang/lib
parentda18ceb4b1d54829f73ae4373b59f6ed30314115 (diff)
downloadllvm-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.cpp35
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;
}
},