From c40d4133702b3d9fc56be26a2d0b48f36d618f94 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Wed, 19 Mar 2025 09:03:05 -0700 Subject: [PATCH] [flang] Catch bad usage case of whole assumed-size array Whole assumed-size arrays are generally not allowed outside specific contexts, where expression analysis notes that they can appear. But contexts can nest, and in the case of an actual argument that turns out to be an array constructor, the permission to use a whole assumed-size array must be rescinded. Fixes https://github.com/llvm/llvm-project/issues/131909. --- flang/include/flang/Semantics/expression.h | 12 ++++++------ flang/lib/Semantics/expression.cpp | 4 +++- flang/test/Semantics/array-constr-values.f90 | 6 +++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h index b051c486641fe..068395072266f 100644 --- a/flang/include/flang/Semantics/expression.h +++ b/flang/include/flang/Semantics/expression.h @@ -258,16 +258,16 @@ class ExpressionAnalyzer { // Builds a typed Designator from an untyped DataRef MaybeExpr Designate(DataRef &&); -protected: - int IntegerTypeSpecKind(const parser::IntegerTypeSpec &); - -private: // Allows a whole assumed-size array to appear for the lifetime of // the returned value. - common::Restorer AllowWholeAssumedSizeArray() { - return common::ScopedSet(isWholeAssumedSizeArrayOk_, true); + common::Restorer AllowWholeAssumedSizeArray(bool yes = true) { + return common::ScopedSet(isWholeAssumedSizeArrayOk_, yes); } +protected: + int IntegerTypeSpecKind(const parser::IntegerTypeSpec &); + +private: // Allows an Expr to be a null pointer. common::Restorer AllowNullPointer() { return common::ScopedSet(isNullPointerOk_, true); diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 39a58a4e23363..74570cdb8eda0 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1915,7 +1915,9 @@ void ArrayConstructorContext::Add(const parser::AcValue::Triplet &triplet) { } void ArrayConstructorContext::Add(const parser::Expr &expr) { - auto restorer{exprAnalyzer_.GetContextualMessages().SetLocation(expr.source)}; + auto restorer1{ + exprAnalyzer_.GetContextualMessages().SetLocation(expr.source)}; + auto restorer2{exprAnalyzer_.AllowWholeAssumedSizeArray(false)}; Push(exprAnalyzer_.Analyze(expr)); } diff --git a/flang/test/Semantics/array-constr-values.f90 b/flang/test/Semantics/array-constr-values.f90 index 6742cd35fe52d..b6558c08089c6 100644 --- a/flang/test/Semantics/array-constr-values.f90 +++ b/flang/test/Semantics/array-constr-values.f90 @@ -2,9 +2,10 @@ ! Confirm enforcement of constraints and restrictions in 7.8 ! C7110, C7111, C7112, C7113, C7114, C7115 -subroutine arrayconstructorvalues() +subroutine arrayconstructorvalues(asize) integer :: intarray(4) integer(KIND=8) :: k8 = 20 + integer, intent(in) :: asize(*) TYPE EMPLOYEE INTEGER AGE @@ -55,6 +56,9 @@ subroutine arrayconstructorvalues() !ERROR: Item is not suitable for use in an array constructor intarray(1:1) = [ arrayconstructorvalues ] + + !ERROR: Whole assumed-size array 'asize' may not appear here without subscripts + intarray = [ asize ] end subroutine arrayconstructorvalues subroutine checkC7115() real, dimension(10), parameter :: good1 = [(99.9, i = 1, 10)]