[flang-commits] [flang] 13893a0 - [flang] Compile-time checking of substring bounds (#71453)
via flang-commits
flang-commits at lists.llvm.org
Mon Nov 13 15:03:21 PST 2023
Author: Peter Klausler
Date: 2023-11-13T15:03:17-08:00
New Revision: 13893a08d91313900857be494ee4702a4f0847af
URL: https://github.com/llvm/llvm-project/commit/13893a08d91313900857be494ee4702a4f0847af
DIFF: https://github.com/llvm/llvm-project/commit/13893a08d91313900857be494ee4702a4f0847af.diff
LOG: [flang] Compile-time checking of substring bounds (#71453)
When the bounds of a substring reference are known during compilation,
and are outside the valid range for the character base object, issue an
error message.
Added:
Modified:
flang/lib/Semantics/expression.cpp
flang/test/Semantics/data17.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index eead0f4787f923c..9aec60304a26c8d 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1059,13 +1059,35 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
const parser::SubstringRange &range{
std::get<parser::SubstringRange>(ss.t)};
std::optional<Expr<SubscriptInteger>> first{
- GetSubstringBound(std::get<0>(range.t))};
+ Fold(GetSubstringBound(std::get<0>(range.t)))};
std::optional<Expr<SubscriptInteger>> last{
- GetSubstringBound(std::get<1>(range.t))};
+ Fold(GetSubstringBound(std::get<1>(range.t)))};
const Symbol &symbol{checked->GetLastSymbol()};
if (std::optional<DynamicType> dynamicType{
DynamicType::From(symbol)}) {
if (dynamicType->category() == TypeCategory::Character) {
+ auto lbValue{ToInt64(first)};
+ if (!lbValue) {
+ lbValue = 1;
+ }
+ auto ubValue{ToInt64(last)};
+ auto len{dynamicType->knownLength()};
+ if (!ubValue) {
+ ubValue = len;
+ }
+ if (lbValue && ubValue && *lbValue > *ubValue) {
+ // valid, substring is empty
+ } else if (lbValue && *lbValue < 1 && (ubValue || !last)) {
+ Say("Substring must begin at 1 or later, not %jd"_err_en_US,
+ static_cast<std::intmax_t>(*lbValue));
+ return std::nullopt;
+ } else if (ubValue && len && *ubValue > *len &&
+ (lbValue || !first)) {
+ Say("Substring must end at %zd or earlier, not %jd"_err_en_US,
+ static_cast<std::intmax_t>(*len),
+ static_cast<std::intmax_t>(*ubValue));
+ return std::nullopt;
+ }
return WrapperHelper<TypeCategory::Character, Designator,
Substring>(dynamicType->kind(),
Substring{std::move(checked.value()), std::move(first),
diff --git a/flang/test/Semantics/data17.f90 b/flang/test/Semantics/data17.f90
index 8ea9d785a96fb83..86f1c4c6c126950 100644
--- a/flang/test/Semantics/data17.f90
+++ b/flang/test/Semantics/data17.f90
@@ -1,11 +1,13 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
-character(4) a, b, c, d, e
+character(4) a, b, c, d, e, f
!WARNING: DATA statement value '"abcde"' for 'a' has the wrong length
data a(1:4)/'abcde'/
!WARNING: DATA statement value '"abc"' for 'b' has the wrong length
data b(1:4)/'abc'/
data c/'abcde'/ ! not a substring, conforms
data d/'abc'/ ! not a substring, conforms
-!ERROR: DATA statement designator 'e(1_8:5_8)' is out of range
-data e(1:5)/'xyz'/
+!ERROR: Substring must end at 4 or earlier, not 5
+data e(1:5)/'abcde'/
+!ERROR: Substring must begin at 1 or later, not 0
+data f(0:4)/'abcde'/
end
More information about the flang-commits
mailing list