Skip to content

Commit dfed044

Browse files
authored
[flang][semantics] fix crash involving equivalences (#168909)
This PR fixes [#166463](#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.
1 parent 3d1f044 commit dfed044

File tree

5 files changed

+107
-6
lines changed

5 files changed

+107
-6
lines changed

flang/lib/Semantics/check-data.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ void DataChecker::Leave(const parser::EntityDecl &decl) {
273273
}
274274

275275
void DataChecker::CompileDataInitializationsIntoInitializers() {
276-
ConvertToInitializers(inits_, exprAnalyzer_);
276+
ConvertToInitializers(inits_, exprAnalyzer_, /*forDerivedTypesOnly=*/false);
277277
}
278278

279279
} // namespace Fortran::semantics

flang/lib/Semantics/data-to-inits.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,14 @@ static bool ProcessScopes(const Scope &scope,
863863
if (std::find_if(associated.begin(), associated.end(), [](SymbolRef ref) {
864864
return IsInitialized(*ref);
865865
}) != associated.end()) {
866+
// If a symbol whose size has not been computed it is possible to get an
867+
// assertion failure when trying to contruct the initializer. The lack
868+
// of a size is assumed to be because there was an error reported that
869+
// blocked computing the size. As of writing this comment, this is only
870+
// called after all of semantics analysis has run without errors. If
871+
// this needs to be called earlier, then we need to skip equivalence
872+
// checking if there are any sizeless symbols and assert that there is
873+
// an error reported.
866874
result &=
867875
CombineEquivalencedInitialization(associated, exprAnalyzer, inits);
868876
}
@@ -944,16 +952,17 @@ void ConstructInitializer(const Symbol &symbol,
944952
}
945953
}
946954

947-
void ConvertToInitializers(
948-
DataInitializations &inits, evaluate::ExpressionAnalyzer &exprAnalyzer) {
955+
void ConvertToInitializers(DataInitializations &inits,
956+
evaluate::ExpressionAnalyzer &exprAnalyzer, bool forDerivedTypesOnly) {
949957
// Process DATA-style component /initializers/ now, so that they appear as
950958
// default values in time for EQUIVALENCE processing in ProcessScopes.
951959
for (auto &[symbolPtr, initialization] : inits) {
952960
if (symbolPtr->owner().IsDerivedType()) {
953961
ConstructInitializer(*symbolPtr, initialization, exprAnalyzer);
954962
}
955963
}
956-
if (ProcessScopes(
964+
if (!forDerivedTypesOnly &&
965+
ProcessScopes(
957966
exprAnalyzer.context().globalScope(), exprAnalyzer, inits)) {
958967
for (auto &[symbolPtr, initialization] : inits) {
959968
if (!symbolPtr->owner().IsDerivedType()) {

flang/lib/Semantics/data-to-inits.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ void AccumulateDataInitializations(DataInitializations &,
6262
evaluate::ExpressionAnalyzer &, const Symbol &,
6363
const std::list<common::Indirection<parser::DataStmtValue>> &);
6464

65-
void ConvertToInitializers(
66-
DataInitializations &, evaluate::ExpressionAnalyzer &);
65+
void ConvertToInitializers(DataInitializations &,
66+
evaluate::ExpressionAnalyzer &, bool forDerivedTypes = true);
6767

6868
} // namespace Fortran::semantics
6969
#endif // FORTRAN_SEMANTICS_DATA_TO_INITS_H_
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
3+
program main
4+
! ERROR: A sequence type should have at least one component [-Wempty-sequence-type]
5+
type t0
6+
sequence
7+
end type
8+
type t1
9+
sequence
10+
integer, dimension(2):: i/41, 2/
11+
end type
12+
type t2
13+
sequence
14+
integer :: j(2) = [42, 2]
15+
end type
16+
! ERROR: Distinct default component initializations of equivalenced objects affect 'o1' more than once
17+
type (t0) :: O1
18+
! ERROR: Distinct default component initializations of equivalenced objects affect 'a%i(1_8)' more than once
19+
type (t1) :: A
20+
! ERROR: Distinct default component initializations of equivalenced objects affect 'b%j(1_8)' more than once
21+
type (t2) :: B
22+
! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
23+
! ERROR: Distinct default component initializations of equivalenced objects affect 'o2(1_8)' more than once
24+
integer :: x, O2(0)
25+
data x/42/
26+
! ERROR: Distinct default component initializations of equivalenced objects affect 'undeclared' more than once
27+
equivalence (A, B, x, O1, O2, Undeclared)
28+
call p(x)
29+
call s()
30+
end
31+
32+
subroutine s()
33+
type g1
34+
sequence
35+
integer(kind=8)::d/1_8/
36+
end type
37+
type g2
38+
sequence
39+
integer(kind=8)::d = 2_8
40+
end type
41+
! ERROR: Distinct default component initializations of equivalenced objects affect 'c%d' more than once
42+
type (g1) :: C
43+
! ERROR: Distinct default component initializations of equivalenced objects affect 'd%d' more than once
44+
type (g2) :: D
45+
! ERROR: Distinct default component initializations of equivalenced objects affect 'x' more than once
46+
! ERROR: Distinct default component initializations of equivalenced objects affect 'y' more than once
47+
integer :: x, y
48+
data x/1/, y/2/
49+
equivalence (C, x)
50+
equivalence (D, y)
51+
equivalence (x, y)
52+
print *, x, y
53+
end subroutine
54+
55+
subroutine p(x)
56+
integer :: x
57+
print *, x
58+
end subroutine
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
3+
! Make sure parameterized derived types can't be used in equivalence sets or contain legacy DATA-style initializations.
4+
program main
5+
type t1
6+
sequence
7+
integer, dimension(2):: i/41, 2/
8+
end type
9+
type pdt(k)
10+
integer, kind :: k
11+
integer, dimension(k + 1):: x = [43, (i, i=2, k+1, 1)]
12+
end type
13+
type pdt1(k)
14+
integer, kind :: k
15+
!ERROR: Component 'x' in a parameterized data type may not be initialized with a legacy DATA-style value list
16+
integer, dimension(k + 1):: x/42, 2/
17+
end type
18+
!ERROR: A sequence type may not have type parameters
19+
type pdt2(k)
20+
integer, kind :: k
21+
sequence
22+
integer, dimension(k + 1):: x = [43, (i, i=2, k+1, 1)]
23+
end type
24+
25+
type (t1) :: A
26+
type (pdt(2)) :: P2
27+
type (pdt(3)) :: P3
28+
type (pdt1(4)) :: P4
29+
type (pdt2(5)) :: P5
30+
! ERROR: Nonsequence derived type object 'p2' is not allowed in an equivalence set
31+
! ERROR: Nonsequence derived type object 'p3' is not allowed in an equivalence set
32+
! ERROR: Nonsequence derived type object 'p4' is not allowed in an equivalence set
33+
equivalence (A, B, P2, P3, P4, P5)
34+
end

0 commit comments

Comments
 (0)