[flang] Handle large integer literals without kinds better
authorpeter klausler <pklausler@nvidia.com>
Thu, 30 May 2019 20:31:11 +0000 (13:31 -0700)
committerpeter klausler <pklausler@nvidia.com>
Thu, 30 May 2019 20:31:11 +0000 (13:31 -0700)
Original-commit: flang-compiler/f18@381ea32d57aa65e52dbde96f6c61baabd95f4dd9
Reviewed-on: https://github.com/flang-compiler/f18/pull/472
Tree-same-pre-rewrite: false

flang/documentation/Extensions.md
flang/lib/parser/features.h
flang/lib/semantics/expression.cc
flang/test/semantics/int-literals.f90

index f0a2e6c..8ecad48 100644 (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
 --------------------------------------------
index 87c2b09..520faf5 100644 (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>;
index 90bfd70..cebbb06 100644 (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);
     }
   }
index 1f71909..6807579 100644 (file)
 ! 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