forked from OSchip/llvm-project
[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
This commit is contained in:
parent
37894ba661
commit
08c7d570d3
|
@ -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
|
||||
---------------------------------------------------------
|
||||
|
|
|
@ -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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -81,7 +81,8 @@ private:
|
|||
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,13 +1744,17 @@ bool ImplicitRulesVisitor::HandleImplicitNone(
|
|||
return false;
|
||||
}
|
||||
prevImplicitNone_ = currStmtSource();
|
||||
bool implicitNoneTypeNever{
|
||||
context().IsEnabled(common::LanguageFeature::ImplicitNoneTypeNever)};
|
||||
if (nameSpecs.empty()) {
|
||||
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};
|
||||
int sawExternal{0};
|
||||
|
@ -1761,6 +1765,7 @@ bool ImplicitRulesVisitor::HandleImplicitNone(
|
|||
++sawExternal;
|
||||
break;
|
||||
case ImplicitNoneNameSpec::Type:
|
||||
if (!implicitNoneTypeNever) {
|
||||
prevImplicitNoneType_ = currStmtSource();
|
||||
implicitRules().set_isImplicitNoneType(true);
|
||||
if (prevImplicit_) {
|
||||
|
@ -1768,6 +1773,7 @@ bool ImplicitRulesVisitor::HandleImplicitNone(
|
|||
return false;
|
||||
}
|
||||
++sawType;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue