* When a name is brought into a scope by multiple ways,
such as USE-association as well as an `IMPORT` from its host,
it's an error only if the resolution is ambiguous.
+* An entity may appear in a `DATA` statement before its explicit
+ type declaration under `IMPLICIT NONE(TYPE)`.
### Extensions supported when enabled by options
ForwardRefImplicitNone, OpenAccessAppend, BOZAsDefaultInteger,
DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
SaveMainProgram, SaveBigMainProgramVariables,
- DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking)
+ DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
+ ForwardRefImplicitNoneData)
// Portability and suspicious usage warnings for conforming code
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
bool CheckPossibleBadForwardRef(const Symbol &);
bool inSpecificationPart_{false};
+ bool inDataStmtObject_{false};
bool inEquivalenceStmt_{false};
// Some information is collected from a specification part for deferred
// or object, it'll be caught later.
return;
}
+ if (inDataStmtObject_) {
+ return;
+ }
if (!context().HasError(symbol)) {
Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
context().SetError(symbol);
}
void ScopeHandler::NotePossibleBadForwardRef(const parser::Name &name) {
- if (inSpecificationPart_ && name.symbol) {
+ if (inSpecificationPart_ && !inDataStmtObject_ && name.symbol) {
auto kind{currScope().kind()};
if ((kind == Scope::Kind::Subprogram && !currScope().IsStmtFunction()) ||
kind == Scope::Kind::BlockConstruct) {
}
auto *prevType{symbol.GetType()};
if (!prevType) {
+ if (symbol.test(Symbol::Flag::InDataStmt) && isImplicitNoneType() &&
+ context().ShouldWarn(
+ common::LanguageFeature::ForwardRefImplicitNoneData)) {
+ Say(name,
+ "'%s' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)"_port_en_US);
+ }
symbol.SetType(type);
} else if (symbol.has<UseDetails>()) {
// error recovery case, redeclaration of use-associated name
auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
common::visit(common::visitors{
[&](const Indirection<parser::Variable> &y) {
+ auto restorer{common::ScopedSet(inDataStmtObject_, true)};
Walk(y.value());
const parser::Name &first{
parser::GetFirstName(y.value())};
}
return &name;
}
- if (isImplicitNoneType()) {
+ if (isImplicitNoneType() && !inDataStmtObject_) {
Say(name, "No explicit type declared for '%s'"_err_en_US);
return nullptr;
}
-! RUN: %python %S/test_errors.py %s %flang_fc1
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
subroutine s1
integer x
block
!ERROR: Must have INTEGER type, but is REAL(4)
data(b(j), j=1, 16) / 16 * 0.0 /
end
+
+subroutine s5
+ implicit none
+ data x/1./
+ !PORTABILITY: 'x' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)
+ real x
+end