[flang] Warn about local names that are the same as their enclosing program unit
authorPeter Klausler <pklausler@nvidia.com>
Mon, 14 Nov 2022 22:38:03 +0000 (14:38 -0800)
committerPeter Klausler <pklausler@nvidia.com>
Sun, 4 Dec 2022 01:47:35 +0000 (17:47 -0800)
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

flang/docs/Extensions.md
flang/lib/Semantics/check-declarations.cpp
flang/test/Semantics/OpenMP/omp-declare-target03.f90
flang/test/Semantics/OpenMP/omp-threadprivate03.f90
flang/test/Semantics/bind-c02.f90
flang/test/Semantics/resolve05.f90
flang/test/Semantics/resolve20.f90

index eea4249..69855bf 100644 (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.
index 4f6109e..4ae4eae 100644 (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);
   }
 }
index 45064ff..c437a3e 100644 (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
index d5ce4a9..2a59a96 100644 (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)
 
index c207e2a..18b9094 100644 (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
index 5c045aa..736babf 100644 (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
index be6fe96..b1d7334 100644 (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'