Skip to content

Conversation

@tmjbios
Copy link
Contributor

@tmjbios tmjbios commented Jan 6, 2026

A substring reference where the lower bound is higher than the upper bound is defined in 9.4.1 to be zero-length.

Thus, a reference to a substring of a CHARACTER*(0) string such as

string(foo():2)

cannot be a compile-time error since we do not know the return value of foo().

We also should not error if the lbound > ubound at compile time.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Jan 6, 2026
@llvmbot
Copy link
Member

llvmbot commented Jan 6, 2026

@llvm/pr-subscribers-flang-semantics

Author: TMJ (tmjbios)

Changes

A substring reference where the lower bound is higher than the upper bound is defined in 9.4.1 to be zero-length.

Thus, a reference to a substring of a CHARACTER*(0) string such as

string(foo():2)

cannot be a compile-time error since we do not know the return value of foo().

We also should not error if the lbound > ubound at compile time.


Full diff: https://github.com/llvm/llvm-project/pull/174511.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/expression.cpp (+2-2)
  • (added) flang/test/Semantics/zero_len_char_array.f90 (+30)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 402e88252fc20..89bc7264707de 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1221,9 +1221,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
                 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 &&
+              } else if (ubValue && len && *len > 0 && *ubValue > *len &&
                   (lbValue || !first)) {
-                Say("Substring must end at %zd or earlier, not %jd"_err_en_US,
+                Say("Substring must end at %jd or earlier, not %jd"_err_en_US,
                     static_cast<std::intmax_t>(*len),
                     static_cast<std::intmax_t>(*ubValue));
                 return std::nullopt;
diff --git a/flang/test/Semantics/zero_len_char_array.f90 b/flang/test/Semantics/zero_len_char_array.f90
new file mode 100644
index 0000000000000..ee9f10fdd6d67
--- /dev/null
+++ b/flang/test/Semantics/zero_len_char_array.f90
@@ -0,0 +1,30 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+! CHECK-NOT: error:
+! Test that zero-length character substrings with lbound>ubounds indices
+! do not produce spurious errors when the character array is zero length.
+
+integer function init(i)
+  integer i
+  init=i
+end
+
+program flang_t7052
+  character*(*), parameter :: param_char = ""
+  character*(0)            :: zero_len_char
+
+  if ( param_char(init(5):init(3)) > zero_len_char(1:-2) ) then
+    print *,"Test failed"
+  endif
+
+  if ( param_char(init(5):init(3)) > zero_len_char(10:2) ) then
+    print *,"Test failed"
+  endif
+
+  if ( param_char(init(5):init(3)) > zero_len_char(init(10):2) ) then
+    print *,"Test failed"
+  endif
+
+  if ( param_char(init(5):init(3)) > zero_len_char(init(10):-2) ) then
+    print *,"Test failed"
+  endif
+end program

@clementval
Copy link
Contributor

Please add a prefix to your commit message so we know it is related to flang ([flang])

@tmjbios tmjbios changed the title Do not error on constant nonzero UB in substring of ZLA [FLANG] Do not error on constant nonzero UB in substring of ZLA Jan 6, 2026
@tmjbios
Copy link
Contributor Author

tmjbios commented Jan 6, 2026

Bah! Sorry about that, Val.

Copy link
Contributor

@akuhlens akuhlens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me.

@klausler klausler removed their request for review January 7, 2026 00:01
Copy link
Contributor

@eugeneepshteyn eugeneepshteyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR.

Could you please also run Fortran tests from llvm-test-suite?

@eugeneepshteyn eugeneepshteyn changed the title [FLANG] Do not error on constant nonzero UB in substring of ZLA [flang] Do not error on constant nonzero UB in substring of ZLA Jan 7, 2026
A substring reference where the lower bound is higher
than the upper bound is defined in 9.4.1 to be zero-length.

Thus, a reference to a substring of a CHARACTER*(0)
string such as

    string(foo():2)

cannot be a compile-time error since we do not know
the return value of foo().

We also should not error if the lbound > ubound at compile time.
* Cleaned up the test
* Moved the zero-len check to the empty array check condition
* Ran "Fortran" llvm-test-suite in addition to check-flang
@tmjbios tmjbios force-pushed the tmjbios/zero_len_char_array branch from 7b7810e to a674969 Compare January 7, 2026 21:53
Copy link
Contributor

@eugeneepshteyn eugeneepshteyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the changes. LGTM!

@tmjbios
Copy link
Contributor Author

tmjbios commented Jan 8, 2026

Thanks!

I don't have permission yet to merge my own PRs, so I'll need someone else to squash & merge.

@eugeneepshteyn
Copy link
Contributor

@tmjbios , did you run Fortran tests from llvm-test-suite with this change?

@tmjbios
Copy link
Contributor Author

tmjbios commented Jan 8, 2026

Yes. I'm still getting used to the various test tools and methods for Flang; in addition to our internal test suite for CCE (where applicable) and the flang "make" lit test targets for flang and flang-rt, I follow this link's instructions for the llvm-test-suite for everything I'm doing:

https://github.com/llvm/llvm-test-suite/blob/main/Fortran/gfortran/README.md#usage
https://github.com/llvm/llvm-project/blob/main/flang/docs/FortranLLVMTestSuite.md

If there is additional pre-commit testing you would like to see us doing religiously, please let me know.

@eugeneepshteyn eugeneepshteyn merged commit fcec9ce into llvm:main Jan 8, 2026
10 checks passed
kshitijvp pushed a commit to kshitijvp/llvm-project that referenced this pull request Jan 9, 2026
…#174511)

A substring reference where the lower bound is higher than the upper
bound is defined in 9.4.1 to be zero-length.

Thus, a reference to a substring of a CHARACTER*(0) string such as

    string(foo():2)

cannot be a compile-time error since we do not know the return value of
foo().

We also should not error if the lbound > ubound at compile time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants