[flang-commits] [flang] dfed044 - [flang][semantics] fix crash involving equivalences (#168909)
via flang-commits
flang-commits at lists.llvm.org
Thu Dec 11 09:16:16 PST 2025
Author: Andre Kuhlenschmidt
Date: 2025-12-11T09:16:09-08:00
New Revision: dfed044c67b8e01b552b0336adea77ae0da42d1f
URL: https://github.com/llvm/llvm-project/commit/dfed044c67b8e01b552b0336adea77ae0da42d1f
DIFF: https://github.com/llvm/llvm-project/commit/dfed044c67b8e01b552b0336adea77ae0da42d1f.diff
LOG: [flang][semantics] fix crash involving equivalences (#168909)
This PR fixes
[#166463](https://github.com/llvm/llvm-project/issues/166463) by only
running ProcessScopes at the end of the semantic analysis. ProcessScopes
does an analysis of the entire symbol table to determine which
equivalence statements have conflicting initializations, but it requires
that all symbols in the equivalence statement have valid sizes. Running
before computing the size and offset made this an invalid assumption.
Added:
flang/test/Semantics/equivalence02.f90
flang/test/Semantics/equivalence03.f90
Modified:
flang/lib/Semantics/check-data.cpp
flang/lib/Semantics/data-to-inits.cpp
flang/lib/Semantics/data-to-inits.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp
index 3bcf711735158..9b41a879ad700 100644
--- a/flang/lib/Semantics/check-data.cpp
+++ b/flang/lib/Semantics/check-data.cpp
@@ -273,7 +273,7 @@ void DataChecker::Leave(const parser::EntityDecl &decl) {
}
void DataChecker::CompileDataInitializationsIntoInitializers() {
- ConvertToInitializers(inits_, exprAnalyzer_);
+ ConvertToInitializers(inits_, exprAnalyzer_, /*forDerivedTypesOnly=*/false);
}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index bbf3b28fe03e6..9012396ebf3b3 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -863,6 +863,14 @@ static bool ProcessScopes(const Scope &scope,
if (std::find_if(associated.begin(), associated.end(), [](SymbolRef ref) {
return IsInitialized(*ref);
}) != associated.end()) {
+ // If a symbol whose size has not been computed it is possible to get an
+ // assertion failure when trying to contruct the initializer. The lack
+ // of a size is assumed to be because there was an error reported that
+ // blocked computing the size. As of writing this comment, this is only
+ // called after all of semantics analysis has run without errors. If
+ // this needs to be called earlier, then we need to skip equivalence
+ // checking if there are any sizeless symbols and assert that there is
+ // an error reported.
result &=
CombineEquivalencedInitialization(associated, exprAnalyzer, inits);
}
@@ -944,8 +952,8 @@ void ConstructInitializer(const Symbol &symbol,
}
}
-void ConvertToInitializers(
- DataInitializations &inits, evaluate::ExpressionAnalyzer &exprAnalyzer) {
+void ConvertToInitializers(DataInitializations &inits,
+ evaluate::ExpressionAnalyzer &exprAnalyzer, bool forDerivedTypesOnly) {
// Process DATA-style component /initializers/ now, so that they appear as
// default values in time for EQUIVALENCE processing in ProcessScopes.
for (auto &[symbolPtr, initialization] : inits) {
@@ -953,7 +961,8 @@ void ConvertToInitializers(
ConstructInitializer(*symbolPtr, initialization, exprAnalyzer);
}
}
- if (ProcessScopes(
+ if (!forDerivedTypesOnly &&
+ ProcessScopes(
exprAnalyzer.context().globalScope(), exprAnalyzer, inits)) {
for (auto &[symbolPtr, initialization] : inits) {
if (!symbolPtr->owner().IsDerivedType()) {
diff --git a/flang/lib/Semantics/data-to-inits.h b/flang/lib/Semantics/data-to-inits.h
index 7486ac8113e90..330a6867a0732 100644
--- a/flang/lib/Semantics/data-to-inits.h
+++ b/flang/lib/Semantics/data-to-inits.h
@@ -62,8 +62,8 @@ void AccumulateDataInitializations(DataInitializations &,
evaluate::ExpressionAnalyzer &, const Symbol &,
const std::list<common::Indirection<parser::DataStmtValue>> &);
-void ConvertToInitializers(
- DataInitializations &, evaluate::ExpressionAnalyzer &);
+void ConvertToInitializers(DataInitializations &,
+ evaluate::ExpressionAnalyzer &, bool forDerivedTypes = true);
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_DATA_TO_INITS_H_
diff --git a/flang/test/Semantics/equivalence02.f90 b/flang/test/Semantics/equivalence02.f90
new file mode 100644
index 0000000000000..87658c20b1f63
--- /dev/null
+++ b/flang/test/Semantics/equivalence02.f90
@@ -0,0 +1,58 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+program main
+! ERROR: A sequence type should have at least one component [-Wempty-sequence-type]
+type t0
+ sequence
+end type
+type t1
+ sequence
+ integer, dimension(2):: i/41, 2/
+end type
+type t2
+ sequence
+ integer :: j(2) = [42, 2]
+end type
+! ERROR: Distinct default component initializations of equivalenced objects affect 'o1' more than once
+type (t0) :: O1
+! ERROR: Distinct default component initializations of equivalenced objects affect 'a%i(1_8)' more than once
+type (t1) :: A
+! ERROR: Distinct default component initializations of equivalenced objects affect 'b%j(1_8)' more than once
+type (t2) :: B
+! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
+! ERROR: Distinct default component initializations of equivalenced objects affect 'o2(1_8)' more than once
+integer :: x, O2(0)
+data x/42/
+! ERROR: Distinct default component initializations of equivalenced objects affect 'undeclared' more than once
+equivalence (A, B, x, O1, O2, Undeclared)
+call p(x)
+call s()
+end
+
+subroutine s()
+ type g1
+ sequence
+ integer(kind=8)::d/1_8/
+ end type
+ type g2
+ sequence
+ integer(kind=8)::d = 2_8
+ end type
+ ! ERROR: Distinct default component initializations of equivalenced objects affect 'c%d' more than once
+ type (g1) :: C
+ ! ERROR: Distinct default component initializations of equivalenced objects affect 'd%d' more than once
+ type (g2) :: D
+ ! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
+ ! ERROR: Distinct default component initializations of equivalenced objects affect 'y' more than once
+ integer :: x, y
+ data x/1/, y/2/
+ equivalence (C, x)
+ equivalence (D, y)
+ equivalence (x, y)
+ print *, x, y
+end subroutine
+
+subroutine p(x)
+ integer :: x
+ print *, x
+end subroutine
diff --git a/flang/test/Semantics/equivalence03.f90 b/flang/test/Semantics/equivalence03.f90
new file mode 100644
index 0000000000000..c97b797230a5a
--- /dev/null
+++ b/flang/test/Semantics/equivalence03.f90
@@ -0,0 +1,34 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+! Make sure parameterized derived types can't be used in equivalence sets or contain legacy DATA-style initializations.
+program main
+type t1
+ sequence
+ integer, dimension(2):: i/41, 2/
+end type
+type pdt(k)
+ integer, kind :: k
+ integer, dimension(k + 1):: x = [43, (i, i=2, k+1, 1)]
+end type
+type pdt1(k)
+ integer, kind :: k
+ !ERROR: Component 'x' in a parameterized data type may not be initialized with a legacy DATA-style value list
+ integer, dimension(k + 1):: x/42, 2/
+end type
+!ERROR: A sequence type may not have type parameters
+type pdt2(k)
+ integer, kind :: k
+ sequence
+ integer, dimension(k + 1):: x = [43, (i, i=2, k+1, 1)]
+end type
+
+type (t1) :: A
+type (pdt(2)) :: P2
+type (pdt(3)) :: P3
+type (pdt1(4)) :: P4
+type (pdt2(5)) :: P5
+! ERROR: Nonsequence derived type object 'p2' is not allowed in an equivalence set
+! ERROR: Nonsequence derived type object 'p3' is not allowed in an equivalence set
+! ERROR: Nonsequence derived type object 'p4' is not allowed in an equivalence set
+equivalence (A, B, P2, P3, P4, P5)
+end
More information about the flang-commits
mailing list