[flang] Special handling for VOLATILE and ASYNCHRONOUS
authorTim Keith <tkeith@nvidia.com>
Tue, 13 Aug 2019 20:50:24 +0000 (13:50 -0700)
committerTim Keith <tkeith@nvidia.com>
Tue, 13 Aug 2019 20:50:24 +0000 (13:50 -0700)
The VOLATILE and ASYNCHRONOUS attributes are special in two ways:
- they can be applied to use-associated variables
- if they are applied to a host-associated variable in a block, that
  variable has the attribute only within the scope of the block

The latter is implemented by making a new `HostAssocDetails` symbol
within the block where the attribute can be set without affecting the
variable in the outer scope. This is similar to how the SHARED locality
spec is implemented.

Fixes flang-compiler/f18#649.

Original-commit: flang-compiler/f18@471aba451341a65ff6014bbe30cb2c64cf905da6
Reviewed-on: https://github.com/flang-compiler/f18/pull/655

flang/lib/semantics/resolve-names.cc
flang/test/semantics/symbol05.f90

index 0697ff9..234fa0c 100644 (file)
@@ -2768,16 +2768,21 @@ Symbol &DeclarationVisitor::HandleAttributeStmt(
     Say(name.source, "'%s' is not a known intrinsic procedure"_err_en_US);
   }
   auto *symbol{FindInScope(currScope(), name)};
-  if (symbol) {
-    // symbol was already there: set attribute on it
-    if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {
-      // TODO: if in a BLOCK, attribute should only be set while in the block
-    } else if (symbol->has<UseDetails>()) {
-      Say(*currStmtSource(),
-          "Cannot change %s attribute on use-associated '%s'"_err_en_US,
-          EnumToString(attr), name.source);
+  if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {
+    // these can be set on a symbol that is host-assoc into block or use-assoc
+    if (!symbol && currScope().kind() == Scope::Kind::Block) {
+      if (auto *hostSymbol{FindSymbol(name)}) {
+        name.symbol = nullptr;
+        symbol = &MakeSymbol(name, HostAssocDetails{*hostSymbol});
+      }
     }
-  } else {
+  } else if (symbol && symbol->has<UseDetails>()) {
+    Say(*currStmtSource(),
+        "Cannot change %s attribute on use-associated '%s'"_err_en_US,
+        EnumToString(attr), name.source);
+    return *symbol;
+  }
+  if (!symbol) {
     symbol = &MakeSymbol(name, EntityDetails{});
   }
   symbol->attrs().set(attr);
index 14c346b..559b654 100644 (file)
@@ -96,3 +96,35 @@ subroutine s5
  !DEF: /s5/x (implicit) ObjectEntity REAL(4)
  x = 1.0
 end subroutine
+
+!DEF: /s6 Subprogram
+subroutine s6
+  !DEF: /s6/i ObjectEntity INTEGER(4)
+  !DEF: /s6/j ObjectEntity INTEGER(4)
+  !DEF: /s6/k ObjectEntity INTEGER(4)
+  integer i, j, k
+  block
+    !DEF: /s6/Block1/i ASYNCHRONOUS, VOLATILE HostAssoc INTEGER(4)
+    volatile :: i
+    !DEF: /s6/Block1/j ASYNCHRONOUS HostAssoc INTEGER(4)
+    asynchronous :: j
+    !REF: /s6/Block1/i
+    asynchronous :: i
+    !DEF: /s6/Block1/k TARGET(implicit) ObjectEntity INTEGER(4)
+    target :: k
+  end block
+end subroutine
+
+!DEF: /m7 Module
+module m7
+  !DEF: /m7/i PUBLIC ObjectEntity INTEGER(4)
+  !DEF: /m7/j PUBLIC ObjectEntity INTEGER(4)
+  integer i, j
+end module
+!DEF: /s7 Subprogram
+subroutine s7
+  !REF: /m7
+  use :: m7
+  !DEF: /s7/j VOLATILE Use INTEGER(4)
+  volatile :: j
+end subroutine