[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.
This commit is contained in:
parent
3d1f04425a
commit
dfed044c67
5 changed files with 107 additions and 6 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
58
flang/test/Semantics/equivalence02.f90
Normal file
58
flang/test/Semantics/equivalence02.f90
Normal file
|
|
@ -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
|
||||
34
flang/test/Semantics/equivalence03.f90
Normal file
34
flang/test/Semantics/equivalence03.f90
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue