[flang] Warn about local names that are the same as their enclosing program unit

Modules, submodules, main programs, and BLOCK DATA subprograms have names
that cannot be used within their scope, so we allow those names to be
used for other entities in the scope.  This might not be entirely
conformant with the language standard, so warn about it.

Differential Revision: https://reviews.llvm.org/D139146
This commit is contained in:
Peter Klausler 2022-11-14 14:38:03 -08:00
parent e86e2ab973
commit dc0d56febb
7 changed files with 48 additions and 4 deletions

View File

@ -513,3 +513,10 @@ end module
application codes that expect exterior symbols whose names match
components to be visible in a derived-type definition's default initialization
expressions, and so f18 follows that precedent.
* 19.3.1p1 "Within its scope, a local identifier of an entity of class (1)
or class (4) shall not be the same as a global identifier used in that scope..."
is read so as to allow the name of a module, submodule, main program,
or `BLOCK DATA` subprogram to also be the name of an local entity in its
scope, with a portability warning, since that global name is not actually
capable of being "used" in its scope.

View File

@ -1857,6 +1857,31 @@ void CheckHelper::Check(const Scope &scope) {
if (scope.kind() == Scope::Kind::BlockData) {
CheckBlockData(scope);
}
if (auto name{scope.GetName()}) {
auto iter{scope.find(*name)};
if (iter != scope.end()) {
const char *kind{nullptr};
switch (scope.kind()) {
case Scope::Kind::Module:
kind = scope.symbol()->get<ModuleDetails>().isSubmodule()
? "submodule"
: "module";
break;
case Scope::Kind::MainProgram:
kind = "main program";
break;
case Scope::Kind::BlockData:
kind = "BLOCK DATA subprogram";
break;
default:;
}
if (kind) {
messages_.Say(iter->second->name(),
"Name '%s' declared in a %s should not have the same name as the %s"_port_en_US,
*name, kind, kind);
}
}
}
CheckGenericOps(scope);
}
}

View File

@ -12,6 +12,7 @@ program main
!ERROR: The module name or main program name cannot be in a DECLARE TARGET directive
!$omp declare target (mod1)
!PORTABILITY: Name 'main' declared in a main program should not have the same name as the main program
!ERROR: The module name or main program name cannot be in a DECLARE TARGET directive
!$omp declare target (main)
end

View File

@ -13,6 +13,7 @@ program main
!ERROR: The module name or main program name cannot be in a THREADPRIVATE directive
!$omp threadprivate(mod1)
!PORTABILITY: Name 'main' declared in a main program should not have the same name as the main program
!ERROR: The module name or main program name cannot be in a THREADPRIVATE directive
!$omp threadprivate(main)

View File

@ -18,6 +18,7 @@ module m
!ERROR: Only variable and named common block can be in BIND statement
bind(c) :: sub
!PORTABILITY: Name 'm' declared in a module should not have the same name as the module
bind(c) :: m ! no error for implicit type variable
type my_type

View File

@ -1,12 +1,20 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
program p
integer :: p ! this is ok
!PORTABILITY: Name 'p' declared in a main program should not have the same name as the main program
integer :: p
end
module m
integer :: m ! this is ok
!PORTABILITY: Name 'm' declared in a module should not have the same name as the module
integer :: m
end
submodule(m) sm
integer :: sm ! this is ok
!PORTABILITY: Name 'sm' declared in a submodule should not have the same name as the submodule
integer :: sm
end
block data bd
!PORTABILITY: Name 'bd' declared in a BLOCK DATA subprogram should not have the same name as the BLOCK DATA subprogram
type bd
end type
end
module m2
type :: t

View File

@ -37,7 +37,8 @@ module m
type :: bad3
end type
type :: m ! the name of a module can be used as a local identifier
!PORTABILITY: Name 'm' declared in a module should not have the same name as the module
type :: m
end type m
!ERROR: EXTERNAL attribute was already specified on 'a'