[flang-commits] [flang] 08c7d57 - [flang] Add options to control IMPLICIT NONE

Tim Keith via flang-commits flang-commits at lists.llvm.org
Thu Aug 6 06:48:23 PDT 2020


Author: Tim Keith
Date: 2020-08-06T06:48:01-07:00
New Revision: 08c7d570d30bb9568fb2219db7b1b8a9532559dd

URL: https://github.com/llvm/llvm-project/commit/08c7d570d30bb9568fb2219db7b1b8a9532559dd
DIFF: https://github.com/llvm/llvm-project/commit/08c7d570d30bb9568fb2219db7b1b8a9532559dd.diff

LOG: [flang] Add options to control IMPLICIT NONE

Add `-fimplicit-none-type-always` to treat each specification-part
like it has `IMPLICIT NONE`. This is helpful for enforcing good Fortran
programming practices. We might consider something similar for
`IMPLICIT NONE(EXTERNAL)` as well.

Add `-fimplicit-none-type-never` to ignore occurrences of `IMPLICIT NONE`
and `IMPLICIT NONE(TYPE)`. This is to handle cases like the one below,
which violates the standard but it accepted by some compilers:
```
subroutine s(a, n)
  implicit none
  real :: a(n)
  integer :: n
end
```

Differential Revision: https://reviews.llvm.org/D85363

Added: 
    flang/test/Semantics/implicit09.f90
    flang/test/Semantics/implicit10.f90

Modified: 
    flang/documentation/Extensions.md
    flang/include/flang/Common/Fortran-features.h
    flang/lib/Semantics/resolve-names.cpp
    flang/tools/f18/f18.cpp

Removed: 
    


################################################################################
diff  --git a/flang/documentation/Extensions.md b/flang/documentation/Extensions.md
index a2420c727e82..8bf5647bd60c 100644
--- a/flang/documentation/Extensions.md
+++ b/flang/documentation/Extensions.md
@@ -139,6 +139,10 @@ Extensions supported when enabled by options
   `FINDLOC`, `MAXLOC`, and `MINLOC` in the absence of an explicit
   `KIND=` actual argument.  We return `INTEGER(KIND=8)` by default in
   these cases when the `-flarge-sizes` option is enabled.
+* Treat each specification-part like is has `IMPLICIT NONE`
+  [-fimplicit-none-type-always]
+* Ignore occurrences of `IMPLICIT NONE` and `IMPLICIT NONE(TYPE)`
+  [-fimplicit-none-type-never]
 
 Extensions and legacy features deliberately not supported
 ---------------------------------------------------------

diff  --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h
index 613aa69cc5d6..ebf7a8d9d623 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ b/flang/include/flang/Common/Fortran-features.h
@@ -28,7 +28,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
     CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals,
     RealDoControls, EquivalenceNumericWithCharacter, AdditionalIntrinsics,
     AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment,
-    EmptySourceFile, ProgramReturn)
+    EmptySourceFile, ProgramReturn, ImplicitNoneTypeNever,
+    ImplicitNoneTypeAlways)
 
 using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
 
@@ -39,6 +40,8 @@ class LanguageFeatureControl {
     disable_.set(LanguageFeature::OldDebugLines);
     disable_.set(LanguageFeature::OpenACC);
     disable_.set(LanguageFeature::OpenMP);
+    disable_.set(LanguageFeature::ImplicitNoneTypeNever);
+    disable_.set(LanguageFeature::ImplicitNoneTypeAlways);
     // These features, if enabled, conflict with valid standard usage,
     // so there are disabled here by default.
     disable_.set(LanguageFeature::BackslashEscapes);

diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index c5b42473d011..b245ef91deaa 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -81,7 +81,8 @@ class ImplicitRules {
   ImplicitRules *parent_;
   SemanticsContext &context_;
   bool inheritFromParent_{false}; // look in parent if not specified here
-  bool isImplicitNoneType_{false};
+  bool isImplicitNoneType_{
+      context_.IsEnabled(common::LanguageFeature::ImplicitNoneTypeAlways)};
   bool isImplicitNoneExternal_{false};
   // map_ contains the mapping between letters and types that were defined
   // by the IMPLICIT statements of the related scope. It does not contain
@@ -1682,9 +1683,8 @@ bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {
                          Say("IMPLICIT statement after IMPLICIT NONE or "
                              "IMPLICIT NONE(TYPE) statement"_err_en_US);
                          return false;
-                       } else {
-                         implicitRules().set_isImplicitNoneType(false);
                        }
+                       implicitRules().set_isImplicitNoneType(false);
                        return true;
                      },
                  },
@@ -1744,12 +1744,16 @@ bool ImplicitRulesVisitor::HandleImplicitNone(
     return false;
   }
   prevImplicitNone_ = currStmtSource();
+  bool implicitNoneTypeNever{
+      context().IsEnabled(common::LanguageFeature::ImplicitNoneTypeNever)};
   if (nameSpecs.empty()) {
-    prevImplicitNoneType_ = currStmtSource();
-    implicitRules().set_isImplicitNoneType(true);
-    if (prevImplicit_) {
-      Say("IMPLICIT NONE statement after IMPLICIT statement"_err_en_US);
-      return false;
+    if (!implicitNoneTypeNever) {
+      prevImplicitNoneType_ = currStmtSource();
+      implicitRules().set_isImplicitNoneType(true);
+      if (prevImplicit_) {
+        Say("IMPLICIT NONE statement after IMPLICIT statement"_err_en_US);
+        return false;
+      }
     }
   } else {
     int sawType{0};
@@ -1761,13 +1765,15 @@ bool ImplicitRulesVisitor::HandleImplicitNone(
         ++sawExternal;
         break;
       case ImplicitNoneNameSpec::Type:
-        prevImplicitNoneType_ = currStmtSource();
-        implicitRules().set_isImplicitNoneType(true);
-        if (prevImplicit_) {
-          Say("IMPLICIT NONE(TYPE) after IMPLICIT statement"_err_en_US);
-          return false;
+        if (!implicitNoneTypeNever) {
+          prevImplicitNoneType_ = currStmtSource();
+          implicitRules().set_isImplicitNoneType(true);
+          if (prevImplicit_) {
+            Say("IMPLICIT NONE(TYPE) after IMPLICIT statement"_err_en_US);
+            return false;
+          }
+          ++sawType;
         }
-        ++sawType;
         break;
       }
     }

diff  --git a/flang/test/Semantics/implicit09.f90 b/flang/test/Semantics/implicit09.f90
new file mode 100644
index 000000000000..30577fccb0f6
--- /dev/null
+++ b/flang/test/Semantics/implicit09.f90
@@ -0,0 +1,11 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fimplicit-none-type-never
+subroutine s1
+  implicit none
+  i = j + k  ! would be error without -fimplicit-none-type-never
+end
+
+subroutine s2(a, n)
+  implicit none
+  real :: a(n)  ! would be error without -fimplicit-none-type-never
+  integer :: n
+end

diff  --git a/flang/test/Semantics/implicit10.f90 b/flang/test/Semantics/implicit10.f90
new file mode 100644
index 000000000000..a77ada8f4893
--- /dev/null
+++ b/flang/test/Semantics/implicit10.f90
@@ -0,0 +1,7 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fimplicit-none-type-always
+
+!ERROR: No explicit type declared for 'f'
+function f()
+  !ERROR: No explicit type declared for 'x'
+  f = x
+end

diff  --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
index 338d04e7e8f5..33c7b6f6ce9e 100644
--- a/flang/tools/f18/f18.cpp
+++ b/flang/tools/f18/f18.cpp
@@ -503,6 +503,12 @@ int main(int argc, char *const argv[]) {
       options.features.Enable(
           Fortran::parser::LanguageFeature::LogicalAbbreviations,
           arg == "-flogical-abbreviations");
+    } else if (arg == "-fimplicit-none-type-always") {
+      options.features.Enable(
+          Fortran::common::LanguageFeature::ImplicitNoneTypeAlways);
+    } else if (arg == "-fimplicit-none-type-never") {
+      options.features.Enable(
+          Fortran::common::LanguageFeature::ImplicitNoneTypeNever);
     } else if (arg == "-fdebug-dump-provenance") {
       driver.dumpProvenance = true;
       options.needProvenanceRangeToCharBlockMappings = true;
@@ -603,7 +609,8 @@ int main(int argc, char *const argv[]) {
       driver.getSymbolsSources = true;
     } else if (arg == "-byteswapio") {
       driver.byteswapio = true; // TODO: Pass to lowering, generate call
-    } else if (arg == "-h" || arg == "-help" || arg == "--help" || arg == "-?") {
+    } else if (arg == "-h" || arg == "-help" || arg == "--help" ||
+        arg == "-?") {
       llvm::errs()
           << "f18: LLVM Fortran compiler\n"
           << "\n"


        


More information about the flang-commits mailing list