`SIZE` that (as mentioned below) may return non-default
`INTEGER` results by default to be passed. A warning is
emitted when truncation is possible.
+* We are not strict on the contents of `BLOCK DATA` subprograms
+ so long as they contain no executable code, no internal subprograms,
+ and allocate no storage outside a named `COMMON` block. (C1415)
Extensions, deletions, and legacy features supported by default
===============================================================
return IsKindTypeParameter(inq.parameter());
}
bool operator()(const semantics::Symbol &symbol) const {
- return IsNamedConstant(symbol);
+ return IsNamedConstant(symbol) || IsImpliedDoIndex(symbol);
}
bool operator()(const CoarrayRef &) const { return false; }
bool operator()(const semantics::ParamValue ¶m) const {
#include "../evaluate/check-expression.h"
#include "../evaluate/fold.h"
#include "../evaluate/tools.h"
-#include <algorithm>
namespace Fortran::semantics {
void CheckHelper::CheckBlockData(const Scope &scope) {
// BLOCK DATA subprograms should contain only named common blocks.
+ // C1415 presents a list of statements that shouldn't appear in
+ // BLOCK DATA, but so long as the subprogram contains no executable
+ // code and allocates no storage outside named COMMON, we're happy
+ // (e.g., an ENUM is strictly not allowed).
for (const auto &pair : scope) {
const Symbol &symbol{*pair.second};
if (!(symbol.has<CommonBlockDetails>() || symbol.has<UseDetails>() ||
"RETURN with expression is only allowed in SUBROUTINE subprogram"_err_en_US);
}
}
- } else {
- context_.Say(
- "RETURN must be in the inclusive scope of a subprogram"_err_en_US);
}
}
bool BeginSubprogram(
const parser::Name &, Symbol::Flag, bool hasModulePrefix = false);
bool BeginMpSubprogram(const parser::Name &);
- Symbol &PushBlockDataScope(const parser::Name &);
+ void PushBlockDataScope(const parser::Name &);
void EndSubprogram();
protected:
return *symbol;
}
-Symbol &SubprogramVisitor::PushBlockDataScope(const parser::Name &name) {
+void SubprogramVisitor::PushBlockDataScope(const parser::Name &name) {
if (auto *prev{FindSymbol(name)}) {
if (prev->attrs().test(Attr::EXTERNAL) && prev->has<ProcEntityDetails>()) {
if (prev->test(Symbol::Flag::Subroutine) ||
EraseSymbol(name);
}
}
- Symbol &symbol{MakeSymbol(name, SubprogramDetails{})};
- PushScope(Scope::Kind::BlockData, &symbol);
- return symbol;
+ PushScope(Scope::Kind::BlockData, &MakeSymbol(name, SubprogramDetails{}));
}
// If name is a generic, return specific subprogram with the same name.
return false;
}
break;
- case Scope::Kind::BlockData:
+ case Scope::Kind::BlockData: // C1415 (in part)
Say("IMPORT is not allowed in a BLOCK DATA subprogram"_err_en_US);
return false;
default:;
inline bool IsProtected(const Symbol &symbol) {
return symbol.attrs().test(Attr::PROTECTED);
}
+inline bool IsImpliedDoIndex(const Symbol &symbol) {
+ return symbol.owner().kind() == Scope::Kind::ImpliedDos;
+}
bool IsFinalizable(const Symbol &);
bool IsFinalizable(const DerivedTypeSpec &);
bool HasImpureFinal(const DerivedTypeSpec &);
+! Test BLOCK DATA subprogram (14.3)
block data foo
+ !ERROR: IMPORT is not allowed in a BLOCK DATA subprogram
+ import
real :: pi = asin(-1.0) ! ok
!ERROR: An initialized variable in BLOCK DATA must be in a COMMON block
integer :: notInCommon = 1