diff options
author | Peter Klausler <pklausler@nvidia.com> | 2022-03-31 15:59:27 -0700 |
---|---|---|
committer | Peter Klausler <pklausler@nvidia.com> | 2022-04-13 18:35:00 -0700 |
commit | a73f7ababb4b2de65c6e2cdd832fc1f8c21207cf (patch) | |
tree | 4ab614a6228e7414a3c25ee62a6aaf12e9e9636d | |
parent | 3a54bbb0f2860b1d4c18b84ea2bc2f8c07330ac8 (diff) | |
download | llvm-a73f7ababb4b2de65c6e2cdd832fc1f8c21207cf.zip llvm-a73f7ababb4b2de65c6e2cdd832fc1f8c21207cf.tar.gz llvm-a73f7ababb4b2de65c6e2cdd832fc1f8c21207cf.tar.bz2 |
[flang] Error handling for out-of-range CASE values
Catch and nicely describe errors in CASE range values
that are out of range for the type of the SELECT CASE.
Differential Revision: https://reviews.llvm.org/D123708
-rw-r--r-- | flang/lib/Semantics/check-case.cpp | 30 | ||||
-rw-r--r-- | flang/test/Semantics/case01.f90 | 21 |
2 files changed, 44 insertions, 7 deletions
diff --git a/flang/lib/Semantics/check-case.cpp b/flang/lib/Semantics/check-case.cpp index 3c52de8..262a685 100644 --- a/flang/lib/Semantics/check-case.cpp +++ b/flang/lib/Semantics/check-case.cpp @@ -79,15 +79,31 @@ private: if (type && type->category() == caseExprType_.category() && (type->category() != TypeCategory::Character || type->kind() == caseExprType_.kind())) { - x->v = evaluate::Fold(context_.foldingContext(), - evaluate::ConvertToType(T::GetType(), std::move(*x->v))); - if (x->v) { - if (auto value{evaluate::GetScalarConstantValue<T>(*x->v)}) { - return *value; + parser::Messages buffer; // discarded folding messages + parser::ContextualMessages foldingMessages{expr.source, &buffer}; + evaluate::FoldingContext foldingContext{ + context_.foldingContext(), foldingMessages}; + auto folded{evaluate::Fold(foldingContext, SomeExpr{*x->v})}; + if (auto converted{evaluate::Fold(foldingContext, + evaluate::ConvertToType(T::GetType(), SomeExpr{folded}))}) { + if (auto value{evaluate::GetScalarConstantValue<T>(*converted)}) { + auto back{evaluate::Fold(foldingContext, + evaluate::ConvertToType(*type, SomeExpr{*converted}))}; + if (back == folded) { + x->v = converted; + return value; + } else { + context_.Say(expr.source, + "CASE value (%s) overflows type (%s) of SELECT CASE expression"_err_en_US, + folded.AsFortran(), caseExprType_.AsFortran()); + hasErrors_ = true; + return std::nullopt; + } } } - context_.Say( - expr.source, "CASE value must be a constant scalar"_err_en_US); + context_.Say(expr.source, + "CASE value (%s) must be a constant scalar"_err_en_US, + x->v->AsFortran()); } else { std::string typeStr{type ? type->AsFortran() : "typeless"s}; context_.Say(expr.source, diff --git a/flang/test/Semantics/case01.f90 b/flang/test/Semantics/case01.f90 index 42eb07d..020f251 100644 --- a/flang/test/Semantics/case01.f90 +++ b/flang/test/Semantics/case01.f90 @@ -177,3 +177,24 @@ program test_overlap case(:0) end select end + +program test_overflow + integer :: j + select case(1_1) + case (127) + !ERROR: CASE value (128_4) overflows type (INTEGER(1)) of SELECT CASE expression + case (128) + !ERROR: CASE value (129_4) overflows type (INTEGER(1)) of SELECT CASE expression + !ERROR: CASE value (130_4) overflows type (INTEGER(1)) of SELECT CASE expression + case (129:130) + !ERROR: CASE value (-130_4) overflows type (INTEGER(1)) of SELECT CASE expression + !ERROR: CASE value (-129_4) overflows type (INTEGER(1)) of SELECT CASE expression + case (-130:-129) + case (-128) + !ERROR: Must be a scalar value, but is a rank-1 array + case ([1, 2]) + !ERROR: Must be a constant value + case (j) + case default + end select +end |