diff --git a/flang/documentation/Extensions.md b/flang/documentation/Extensions.md --- a/flang/documentation/Extensions.md +++ b/flang/documentation/Extensions.md @@ -139,6 +139,10 @@ `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 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -28,7 +28,8 @@ CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals, RealDoControls, EquivalenceNumericWithCharacter, AdditionalIntrinsics, AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment, - EmptySourceFile, ProgramReturn) + EmptySourceFile, ProgramReturn, ImplicitNoneTypeNever, + ImplicitNoneTypeAlways) using LanguageFeatures = EnumSet; @@ -39,6 +40,8 @@ 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 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -81,7 +81,8 @@ 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 @@ 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 @@ 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 @@ ++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 --- /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 --- /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 --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -503,6 +503,12 @@ 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 @@ 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"