[flang-commits] [flang] 2ce7432 - [flang] Enabling automatic declaration of names in SHARED locality-spec's

Peter Steinfeld via flang-commits flang-commits at lists.llvm.org
Thu Apr 9 08:15:35 PDT 2020


Author: Peter Steinfeld
Date: 2019-07-10T12:53:55-07:00
New Revision: 2ce7432bb8b353eb011a15645187b5bdeda8039b

URL: https://github.com/llvm/llvm-project/commit/2ce7432bb8b353eb011a15645187b5bdeda8039b
DIFF: https://github.com/llvm/llvm-project/commit/2ce7432bb8b353eb011a15645187b5bdeda8039b.diff

LOG: [flang] Enabling automatic declaration of names in SHARED locality-spec's

Prior to this change, the compiler issued an error message when a name in a
SHARED locality-spec had not been declared explicitly in an enclosing scope.
Presumably, this was done to enforce constraint C1124.  This constraint states
that "A variable-name in a locality-spec shall be the name of a variable in the
innermost executable construct or scoping unit that includes the DO CONCURRENT
statement".  For LOCAL and LOCAL_INIT locality-spec's, we were automatically
creating a local variable in the situation where one had not been explicitly
declared rather than issuing an error message.

The only compiler I could find that implements the SHARED locality-spec was the
PGI compiler, which automatically creates a variable and does not emit an error
message.  Also, @vdonaldson said that he had consulted with a member of the
Fortran standards committee who said that the correct thing was to create a
variable if necessary.

This change has the compiler creating a variable in the enclosing scope of a DO
CONCURRENT statement if necessary.  I also changed a test to adapt to the new
behavior.  I also consolidated the semantic checking for the constraints
associated with all of the locality-spec's.

Original-commit: flang-compiler/f18 at d9253a76fcbc49df11c017557b365dfeed7c2b3b
Reviewed-on: https://github.com/flang-compiler/f18/pull/551
Tree-same-pre-rewrite: false

Added: 
    

Modified: 
    flang/lib/semantics/resolve-names.cc
    flang/test/semantics/resolve35.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc
index 6313e7469d3d..fa742d563288 100644
--- a/flang/lib/semantics/resolve-names.cc
+++ b/flang/lib/semantics/resolve-names.cc
@@ -746,6 +746,8 @@ class DeclarationVisitor : public ArraySpecVisitor,
   bool BeginDecl();
   void EndDecl();
   Symbol &DeclareObjectEntity(const parser::Name &, Attrs);
+  // Make sure that there's an entity in an enclosing scope called Name
+  Symbol *EnsureEnclosingEntity(const parser::Name &);
   // Declare a LOCAL/LOCAL_INIT entity. If there isn't a type specified
   // it comes from the entity in the containing scope, or implicit rules.
   // Return pointer to the new symbol, or nullptr on error.
@@ -772,6 +774,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
   const parser::Name *ResolveDataRef(const parser::DataRef &);
   const parser::Name *ResolveVariable(const parser::Variable &);
   const parser::Name *ResolveName(const parser::Name &);
+  bool PassesSharedLocalityChecks(const parser::Name &name, Symbol &symbol);
 
 private:
   // The attribute corresponding to the statement containing an ObjectDecl
@@ -3725,12 +3728,26 @@ bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
   }
 }
 
-bool DeclarationVisitor::PassesLocalityChecks(
+// Checks for all locality-specs: LOCAL, LOCAL_INIT, and SHARED
+bool DeclarationVisitor::PassesSharedLocalityChecks(
     const parser::Name &name, Symbol &symbol) {
   if (!IsVariableName(symbol)) {
     SayLocalMustBeVariable(name, symbol);  // C1124
     return false;
   }
+  if (symbol.owner() == currScope()) {  // C1125 and C1126
+    SayAlreadyDeclared(name, symbol);
+    return false;
+  }
+  return true;
+}
+
+// Checks for locality-specs LOCAL and LOCAL_INIT
+bool DeclarationVisitor::PassesLocalityChecks(
+    const parser::Name &name, Symbol &symbol) {
+  if (!PassesSharedLocalityChecks(name, symbol)) {
+    return false;
+  }
   if (IsAllocatable(symbol)) {  // C1128
     SayWithDecl(name, symbol,
         "ALLOCATABLE variable '%s' not allowed in a locality-spec"_err_en_US);
@@ -3770,35 +3787,33 @@ bool DeclarationVisitor::PassesLocalityChecks(
         "Assumed size array '%s' not allowed in a locality-spec"_err_en_US);
     return false;
   }
-  if (symbol.owner() == currScope()) {  // C1125 and C1126
-    SayAlreadyDeclared(name, symbol);
-    return false;
-  }
   // TODO: Check to see if the name can appear in a variable definition context
   return true;
 }
 
-Symbol *DeclarationVisitor::DeclareLocalEntity(const parser::Name &name) {
+Symbol *DeclarationVisitor::EnsureEnclosingEntity(const parser::Name &name) {
   Symbol *prev{FindSymbol(name)};
-  bool implicit{false};
   if (prev == nullptr) {
     // Declare the name as an object in the enclosing scope so that
     // the name can't be repurposed there later as something else.
     prev = &MakeSymbol(InclusiveScope(), name.source, Attrs{});
     ConvertToObjectEntity(*prev);
     ApplyImplicitRules(*prev);
-    implicit = true;
   }
+  return prev;
+}
+
+Symbol *DeclarationVisitor::DeclareLocalEntity(const parser::Name &name) {
+  Symbol *prev{EnsureEnclosingEntity(name)};
   if (!PassesLocalityChecks(name, *prev)) {
     return nullptr;
   }
   name.symbol = nullptr;
   Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, {})};
   if (auto *type{prev->GetType()}) {
-    if (implicit) {
-      ApplyImplicitRules(symbol);
-    } else {
-      symbol.SetType(*type);
+    symbol.SetType(*type);
+    if (prev->test(Symbol::Flag::Implicit)) {
+      symbol.set(Symbol::Flag::Implicit);
     }
   }
   return &symbol;
@@ -4091,16 +4106,8 @@ bool ConstructVisitor::Pre(const parser::LocalitySpec::LocalInit &x) {
 
 bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) {
   for (const auto &name : x.v) {
-    Symbol *prev{FindSymbol(name)};
-    if (!prev) {
-      Say(name, "Variable '%s' not found"_err_en_US);
-      context().SetError(
-          MakeSymbol(name, ObjectEntityDetails{EntityDetails{}}));
-    } else if (prev->owner() == currScope()) {
-      SayAlreadyDeclared(name, *prev);  // C1125 and C1126
-    } else if (!IsVariableName(*prev)) {
-      SayLocalMustBeVariable(name, *prev);  // C1124
-    } else {
+    Symbol *prev{EnsureEnclosingEntity(name)};
+    if (PassesSharedLocalityChecks(name, *prev)) {
       auto &symbol{MakeSymbol(name, HostAssocDetails{*prev})};
       symbol.set(Symbol::Flag::LocalityShared);
       name.symbol = &symbol;  // override resolution to parent

diff  --git a/flang/test/semantics/resolve35.f90 b/flang/test/semantics/resolve35.f90
index d5433ab7fbb1..c2ec8cc8811d 100644
--- a/flang/test/semantics/resolve35.f90
+++ b/flang/test/semantics/resolve35.f90
@@ -88,7 +88,6 @@ subroutine s7
   do concurrent(integer::i=1:5) local(j, i) &
       !ERROR: 'j' is already declared in this scoping unit
       local_init(k, j) &
-      !ERROR: Variable 'a' not found
       shared(a)
     a(i) = j + 1
   end do


        


More information about the flang-commits mailing list