[flang] Handle large integer literals without kinds better

Original-commit: flang-compiler/f18@381ea32d57
Reviewed-on: https://github.com/flang-compiler/f18/pull/472
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler
2019-05-30 13:31:11 -07:00
parent 616337dbf3
commit d3b23e9dd6
4 changed files with 45 additions and 21 deletions

View File

@@ -63,6 +63,9 @@ Extensions, deletions, and legacy features supported by default
* $ and \ edit descriptors are supported in FORMAT to suppress newline
output on user prompts.
* REAL variable and bounds in DO loops
* Integer literals without explicit kind specifiers that are out of range
for the default kind of INTEGER are assumed to have the least larger kind
that can hold them, if one exists.
Extensions supported when enabled by options
--------------------------------------------

View File

@@ -30,7 +30,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
Convert, Dispose, IOListLeadingComma, AbbreviatedEditDescriptor,
ProgramParentheses, PercentRefAndVal, OmitFunctionDummies, CrayPointer,
Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenMP,
CruftAfterAmpersand, ClassicCComments, AdditionalFormats)
CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals)
using LanguageFeatures =
common::EnumSet<LanguageFeature, LanguageFeature_enumSize>;

View File

@@ -357,30 +357,51 @@ struct IntTypeVisitor {
using Result = MaybeExpr;
using Types = IntegerTypes;
template<typename T> Result Test() {
if (T::kind == kind) {
if (T::kind >= kind) {
const char *p{digits.begin()};
auto value{T::Scalar::Read(p, 10, true)};
auto value{T::Scalar::Read(p, 10, true /*signed*/)};
if (!value.overflow) {
if (T::kind > kind) {
if (!isDefaultKind ||
!analyzer.context().IsEnabled(
parser::LanguageFeature::BigIntLiterals)) {
return std::nullopt;
} else if (analyzer.context().ShouldWarn(
parser::LanguageFeature::BigIntLiterals)) {
analyzer.Say(digits,
"Integer literal is too large for default INTEGER(KIND=%d); "
"assuming INTEGER(KIND=%d)"_en_US,
kind, T::kind);
}
}
return Expr<SomeType>{
Expr<SomeInteger>{Expr<T>{Constant<T>{std::move(value.value)}}}};
}
}
return std::nullopt;
}
ExpressionAnalyzer &analyzer;
parser::CharBlock digits;
int kind;
bool isDefaultKind;
};
template<typename PARSED>
MaybeExpr ExpressionAnalyzer::IntLiteralConstant(const PARSED &x) {
int kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
GetDefaultKind(TypeCategory::Integer))};
const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
bool isDefaultKind{!kindParam.has_value()};
int kind{AnalyzeKindParam(kindParam, GetDefaultKind(TypeCategory::Integer))};
if (CheckIntrinsicKind(TypeCategory::Integer, kind)) {
auto digits{std::get<parser::CharBlock>(x.t)};
if (MaybeExpr result{common::SearchTypes(IntTypeVisitor{digits, kind})}) {
if (MaybeExpr result{common::SearchTypes(
IntTypeVisitor{*this, digits, kind, isDefaultKind})}) {
return result;
} else if (isDefaultKind) {
Say(digits,
"Integer literal is too large for any allowable "
"kind of INTEGER"_err_en_US);
} else {
Say(digits, "Integer literal too large for INTEGER(KIND=%d)"_err_en_US,
Say(digits, "Integer literal is too large for INTEGER(KIND=%d)"_err_en_US,
kind);
}
}

View File

@@ -19,48 +19,48 @@
! as part of expressions that name resolution must analyze.
complex, parameter :: okj1 = 127_1, okz1 = (+127_1, -128_1)
!ERROR: Integer literal too large for INTEGER(KIND=1)
!ERROR: Integer literal is too large for INTEGER(KIND=1)
complex, parameter :: badj1 = 128_1
!ERROR: Integer literal too large for INTEGER(KIND=1)
!ERROR: Integer literal is too large for INTEGER(KIND=1)
complex, parameter :: badz1 = (+128_1, 0)
complex, parameter :: okj1a = 128_2
complex, parameter :: okz1a = (+128_2, 0)
complex, parameter :: okj2 = 32767_2, okz2 = (+32767_2, -32768_2)
!ERROR: Integer literal too large for INTEGER(KIND=2)
!ERROR: Integer literal is too large for INTEGER(KIND=2)
complex, parameter :: badj2 = 32768_2
!ERROR: Integer literal too large for INTEGER(KIND=2)
!ERROR: Integer literal is too large for INTEGER(KIND=2)
complex, parameter :: badz2 = (+32768_2, 0)
complex, parameter :: okj2a = 32768_4
complex, parameter :: okz2a = (+32768_4, 0)
complex, parameter :: okj4 = 2147483647_4, okz4 = (+2147483647_4, -2147483648_4)
!ERROR: Integer literal too large for INTEGER(KIND=4)
!ERROR: Integer literal is too large for INTEGER(KIND=4)
complex, parameter :: badj4 = 2147483648_4
!ERROR: Integer literal too large for INTEGER(KIND=4)
!ERROR: Integer literal is too large for INTEGER(KIND=4)
complex, parameter :: badz4 = (+2147483648_4, 0)
complex, parameter :: okj4a = 2147483648_8
complex, parameter :: okz4a = (+2147483648_8, 0)
complex, parameter :: okj4d = 2147483647, okz4d = (+2147483647, -2147483648)
!ERROR: Integer literal too large for INTEGER(KIND=4)
complex, parameter :: badj4d = 2147483648
!ERROR: Integer literal too large for INTEGER(KIND=4)
complex, parameter :: badz4d = (+2147483648, 0)
!WARNING: Integer literal is too large for default INTEGER(KIND=4); assuming INTEGER(KIND=8)
complex, parameter :: badj4dext = 2147483648
!WARNING: Integer literal is too large for default INTEGER(KIND=4); assuming INTEGER(KIND=8)
complex, parameter :: badz4dext = (+2147483648, 0)
complex, parameter :: okj8 = 9223372036854775807_8, okz8 = (+9223372036854775807_8, -9223372036854775808_8)
!ERROR: Integer literal too large for INTEGER(KIND=8)
!ERROR: Integer literal is too large for INTEGER(KIND=8)
complex, parameter :: badj8 = 9223372036854775808_8
!ERROR: Integer literal too large for INTEGER(KIND=8)
!ERROR: Integer literal is too large for INTEGER(KIND=8)
complex, parameter :: badz8 = (+9223372036854775808_8, 0)
complex, parameter :: okj8a = 9223372036854775808_16
complex, parameter :: okz8a = (+9223372036854775808_16, 0)
complex, parameter :: okj16 = 170141183460469231731687303715884105727_16
complex, parameter :: okz16 = (+170141183460469231731687303715884105727_16, -170141183460469231731687303715884105728_16)
!ERROR: Integer literal too large for INTEGER(KIND=16)
!ERROR: Integer literal is too large for INTEGER(KIND=16)
complex, parameter :: badj16 = 170141183460469231731687303715884105728_16
!ERROR: Integer literal too large for INTEGER(KIND=16)
!ERROR: Integer literal is too large for INTEGER(KIND=16)
complex, parameter :: badz16 = (+170141183460469231731687303715884105728_16, 0)
end