Skip to content

[flang] Catch more semantic errors with coarrays #125536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 27, 2025
Merged

Conversation

klausler
Copy link
Contributor

@klausler klausler commented Feb 3, 2025

Detect and report a bunch of uncaught semantic errors with coarray declarations. Add more tests, and clean up bad usage in existing tests.

Detect and report a bunch of uncaught semantic errors with
coarray declarations.  Add more tests, and clean up bad usage
in existing tests.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:semantics labels Feb 3, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 3, 2025

@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-fir-hlfir

Author: Peter Klausler (klausler)

Changes

Detect and report a bunch of uncaught semantic errors with coarray declarations. Add more tests, and clean up bad usage in existing tests.


Patch is 26.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125536.diff

26 Files Affected:

  • (modified) flang/include/flang/Semantics/tools.h (+2)
  • (modified) flang/lib/Evaluate/tools.cpp (+5-1)
  • (modified) flang/lib/Semantics/check-declarations.cpp (+80-18)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+15-26)
  • (modified) flang/lib/Semantics/tools.cpp (+7)
  • (modified) flang/test/Lower/pre-fir-tree04.f90 (+1)
  • (modified) flang/test/Semantics/allocate11.f90 (+14-4)
  • (modified) flang/test/Semantics/assign02.f90 (+3-3)
  • (modified) flang/test/Semantics/associated.f90 (+1-1)
  • (modified) flang/test/Semantics/bind-c09.f90 (+1-1)
  • (modified) flang/test/Semantics/call10.f90 (+3-2)
  • (modified) flang/test/Semantics/call12.f90 (+4-2)
  • (modified) flang/test/Semantics/change_team01.f90 (+1)
  • (modified) flang/test/Semantics/coarrays01.f90 (+3-3)
  • (added) flang/test/Semantics/coarrays02.f90 (+50)
  • (modified) flang/test/Semantics/critical02.f90 (+1-1)
  • (modified) flang/test/Semantics/doconcurrent01.f90 (+3-4)
  • (modified) flang/test/Semantics/doconcurrent08.f90 (+2-2)
  • (modified) flang/test/Semantics/form_team01.f90 (+1-2)
  • (modified) flang/test/Semantics/init01.f90 (+1)
  • (modified) flang/test/Semantics/resolve07.f90 (+1)
  • (modified) flang/test/Semantics/resolve50.f90 (+2-1)
  • (modified) flang/test/Semantics/resolve55.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve88.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve94.f90 (+1)
  • (modified) flang/test/Semantics/this_image01.f90 (+1-1)
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 87ddd38e5ae655b..dbdae37e4551c63 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -630,6 +630,8 @@ using PotentialAndPointerComponentIterator =
 // dereferenced.
 PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent(
     const DerivedTypeSpec &, bool ignoreCoarrays = false);
+PotentialComponentIterator::const_iterator FindCoarrayPotentialComponent(
+    const DerivedTypeSpec &);
 UltimateComponentIterator::const_iterator FindCoarrayUltimateComponent(
     const DerivedTypeSpec &);
 UltimateComponentIterator::const_iterator FindPointerUltimateComponent(
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 16b026071909738..7181265b862fb13 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1812,7 +1812,11 @@ bool IsSaved(const Symbol &original) {
   } else if (scopeKind == Scope::Kind::DerivedType) {
     return false; // this is a component
   } else if (symbol.attrs().test(Attr::SAVE)) {
-    return true; // explicit SAVE attribute
+    // explicit or implied SAVE attribute
+    // N.B.: semantics sets implied SAVE for main program
+    // local variables whose derived types have coarray
+    // potential subobject components.
+    return true;
   } else if (IsDummy(symbol) || IsFunctionResult(symbol) ||
       IsAutomatic(symbol) || IsNamedConstant(symbol)) {
     return false;
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 5c26469b9fa2482..712347ff0a37b37 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -683,20 +683,10 @@ void CheckHelper::CheckObjectEntity(
   const DeclTypeSpec *type{details.type()};
   const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr};
   bool isComponent{symbol.owner().IsDerivedType()};
-  if (details.coshape().empty()) { // not a coarray
-    if (!isComponent && !IsPointer(symbol) && derived) {
-      if (IsEventTypeOrLockType(derived)) {
-        messages_.Say(
-            "Variable '%s' with EVENT_TYPE or LOCK_TYPE must be a coarray"_err_en_US,
-            symbol.name());
-      } else if (auto component{FindEventOrLockPotentialComponent(
-                     *derived, /*ignoreCoarrays=*/true)}) {
-        messages_.Say(
-            "Variable '%s' with EVENT_TYPE or LOCK_TYPE potential component '%s' must be a coarray"_err_en_US,
-            symbol.name(), component.BuildResultDesignatorName());
-      }
-    }
-  } else { // it's a coarray
+  const Symbol *commonBlock{FindCommonBlockContaining(symbol)};
+  bool isLocalVariable{!commonBlock && !isComponent && !details.isDummy() &&
+      symbol.owner().kind() != Scope::Kind::OtherConstruct};
+  if (int corank{evaluate::GetCorank(symbol)}; corank > 0) { // it's a coarray
     bool isDeferredCoshape{details.coshape().CanBeDeferredShape()};
     if (IsAllocatable(symbol)) {
       if (!isDeferredCoshape) { // C827
@@ -726,6 +716,46 @@ void CheckHelper::CheckObjectEntity(
       messages_.Say("Coarray '%s' may not be an assumed-rank array"_err_en_US,
           symbol.name());
     }
+    if (IsNamedConstant(symbol)) {
+      messages_.Say(
+          "Coarray '%s' may not be a named constant"_err_en_US, symbol.name());
+    }
+    if (IsFunctionResult(symbol)) {
+      messages_.Say("Function result may not be a coarray"_err_en_US);
+    } else if (commonBlock) {
+      messages_.Say("Coarray '%s' may not be in COMMON block '/%s/'"_err_en_US,
+          symbol.name(), commonBlock->name());
+    } else if (isLocalVariable && !IsAllocatableOrPointer(symbol) &&
+        !IsSaved(symbol)) {
+      messages_.Say("Local coarray must have the SAVE attribute"_err_en_US);
+    }
+    for (int j{0}; j < corank; ++j) {
+      if (auto lcbv{evaluate::ToInt64(evaluate::Fold(
+              context().foldingContext(), evaluate::GetLCOBOUND(symbol, j)))}) {
+        if (auto ucbv{
+                evaluate::ToInt64(evaluate::Fold(context().foldingContext(),
+                    evaluate::GetUCOBOUND(symbol, j)))}) {
+          if (ucbv < lcbv) {
+            messages_.Say(
+                "Cobounds %jd:%jd of codimension %d produce an empty coarray"_err_en_US,
+                std::intmax_t{*lcbv}, std::intmax_t{*ucbv}, j + 1);
+          }
+        }
+      }
+    }
+  } else { // not a coarray
+    if (!isComponent && !IsPointer(symbol) && derived) {
+      if (IsEventTypeOrLockType(derived)) {
+        messages_.Say(
+            "Variable '%s' with EVENT_TYPE or LOCK_TYPE must be a coarray"_err_en_US,
+            symbol.name());
+      } else if (auto component{FindEventOrLockPotentialComponent(
+                     *derived, /*ignoreCoarrays=*/true)}) {
+        messages_.Say(
+            "Variable '%s' with EVENT_TYPE or LOCK_TYPE potential component '%s' must be a coarray"_err_en_US,
+            symbol.name(), component.BuildResultDesignatorName());
+      }
+    }
   }
   if (details.isDummy()) {
     if (IsIntentOut(symbol)) {
@@ -926,6 +956,42 @@ void CheckHelper::CheckObjectEntity(
         symbol.name());
   }
 
+  if (derived) {
+    bool isUnsavedLocal{
+        isLocalVariable && !IsAllocatable(symbol) && !IsSaved(symbol)};
+    if (IsFunctionResult(symbol) || IsPointer(symbol) ||
+        evaluate::IsCoarray(symbol) || isUnsavedLocal) {
+      if (auto badPotential{FindCoarrayPotentialComponent(*derived)}) {
+        if (IsFunctionResult(symbol)) { // F'2023 C825
+          SayWithDeclaration(*badPotential,
+              "Function result '%s' may not have a coarray potential component '%s'"_err_en_US,
+              symbol.name(), badPotential.BuildResultDesignatorName());
+        } else if (IsPointer(symbol)) { // F'2023 C825
+          SayWithDeclaration(*badPotential,
+              "Pointer '%s' may not have a coarray potential component '%s'"_err_en_US,
+              symbol.name(), badPotential.BuildResultDesignatorName());
+        } else if (evaluate::IsCoarray(symbol)) { // F'2023 C825
+          SayWithDeclaration(*badPotential,
+              "Coarray '%s' may not have a coarray potential component '%s'"_err_en_US,
+              symbol.name(), badPotential.BuildResultDesignatorName());
+        } else if (isUnsavedLocal) { // F'2023 C826
+          SayWithDeclaration(*badPotential,
+              "Local variable '%s' without the SAVE attribute may not have a coarray potential subobject component '%s'"_err_en_US,
+              symbol.name(), badPotential.BuildResultDesignatorName());
+        } else {
+          DIE("caught unexpected bad coarray potential component");
+        }
+      }
+    } else if (isComponent && (IsAllocatable(symbol) || symbol.Rank() > 0)) {
+      if (auto badUltimate{FindCoarrayUltimateComponent(*derived)}) {
+        // TODO: still an error in F'2023?
+        SayWithDeclaration(*badUltimate,
+            "Allocatable or array component '%s' may not have a coarray ultimate component '%s'"_err_en_US,
+            symbol.name(), badUltimate.BuildResultDesignatorName());
+      }
+    }
+  }
+
   // Check CUDA attributes and special circumstances of being in device
   // subprograms
   const Scope &progUnit{GetProgramUnitContaining(symbol)};
@@ -3161,10 +3227,6 @@ parser::Messages CheckHelper::WhyNotInteroperableFunctionResult(
     msgs.Say(symbol.name(),
         "Interoperable function result must be scalar"_err_en_US);
   }
-  if (symbol.Corank()) {
-    msgs.Say(symbol.name(),
-        "Interoperable function result may not be a coarray"_err_en_US);
-  }
   return msgs;
 }
 
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index c4562727f09b3f4..a1f4b0f54b9948c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6043,32 +6043,6 @@ void DeclarationVisitor::Post(const parser::ComponentDecl &x) {
               "POINTER or ALLOCATABLE"_err_en_US);
         }
       }
-      // TODO: This would be more appropriate in CheckDerivedType()
-      if (auto it{FindCoarrayUltimateComponent(*derived)}) { // C748
-        std::string ultimateName{it.BuildResultDesignatorName()};
-        // Strip off the leading "%"
-        if (ultimateName.length() > 1) {
-          ultimateName.erase(0, 1);
-          if (attrs.HasAny({Attr::POINTER, Attr::ALLOCATABLE})) {
-            evaluate::AttachDeclaration(
-                Say(name.source,
-                    "A component with a POINTER or ALLOCATABLE attribute may "
-                    "not "
-                    "be of a type with a coarray ultimate component (named "
-                    "'%s')"_err_en_US,
-                    ultimateName),
-                derived->typeSymbol());
-          }
-          if (!arraySpec().empty() || !coarraySpec().empty()) {
-            evaluate::AttachDeclaration(
-                Say(name.source,
-                    "An array or coarray component may not be of a type with a "
-                    "coarray ultimate component (named '%s')"_err_en_US,
-                    ultimateName),
-                derived->typeSymbol());
-          }
-        }
-      }
     }
   }
   if (OkToAddComponent(name)) {
@@ -9804,6 +9778,21 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
         object->set_cudaDataAttr(common::CUDADataAttr::Device);
       }
     }
+    // Main program local objects usually don't have an implied SAVE attribute,
+    // as one might think, but in the exceptional case of a derived type
+    // local object that contains a coarray, we have to mark it as an
+    // implied SAVE so that evaluate::IsSaved() will return true.
+    if (node.scope()->kind() == Scope::Kind::MainProgram) {
+      if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
+        if (const DeclTypeSpec * type{object->type()}) {
+          if (const DerivedTypeSpec * derived{type->AsDerived()}) {
+            if (!IsSaved(symbol) && FindCoarrayPotentialComponent(*derived)) {
+              SetImplicitAttr(symbol, Attr::SAVE);
+            }
+          }
+        }
+      }
+    }
   }
 }
 
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 9ebfbbb5317b662..b28ca61eafe9373 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -1386,6 +1386,13 @@ template class ComponentIterator<ComponentKind::Potential>;
 template class ComponentIterator<ComponentKind::Scope>;
 template class ComponentIterator<ComponentKind::PotentialAndPointer>;
 
+PotentialComponentIterator::const_iterator FindCoarrayPotentialComponent(
+    const DerivedTypeSpec &derived) {
+  PotentialComponentIterator potentials{derived};
+  return std::find_if(potentials.begin(), potentials.end(),
+      [](const Symbol &symbol) { return evaluate::IsCoarray(symbol); });
+}
+
 UltimateComponentIterator::const_iterator FindCoarrayUltimateComponent(
     const DerivedTypeSpec &derived) {
   UltimateComponentIterator ultimates{derived};
diff --git a/flang/test/Lower/pre-fir-tree04.f90 b/flang/test/Lower/pre-fir-tree04.f90
index e5f804245854211..07077ff0473dded 100644
--- a/flang/test/Lower/pre-fir-tree04.f90
+++ b/flang/test/Lower/pre-fir-tree04.f90
@@ -5,6 +5,7 @@
 ! CHECK: Subroutine test_coarray
 Subroutine test_coarray
   use iso_fortran_env, only: team_type, event_type, lock_type
+  save
   type(team_type) :: t
   type(event_type) :: done[*]
   type(lock_type) :: alock[*]
diff --git a/flang/test/Semantics/allocate11.f90 b/flang/test/Semantics/allocate11.f90
index 6440248b6f4a96d..1b7495e9fc07d77 100644
--- a/flang/test/Semantics/allocate11.f90
+++ b/flang/test/Semantics/allocate11.f90
@@ -38,7 +38,14 @@ subroutine C937(var)
 
   type B
     type(A) y
-    !ERROR: A component with a POINTER or ALLOCATABLE attribute may not be of a type with a coarray ultimate component (named 'y%x')
+    !ERROR: Allocatable or array component 'forward' may not have a coarray ultimate component '%y%x'
+    type(B), allocatable :: forward
+    real :: u
+  end type
+
+  type B2
+    type(A) y
+    !ERROR: Pointer 'forward' may not have a coarray potential component '%y%x'
     type(B), pointer :: forward
     real :: u
   end type
@@ -48,11 +55,14 @@ subroutine C937(var)
   end type
 
   type D
-    !ERROR: A component with a POINTER or ALLOCATABLE attribute may not be of a type with a coarray ultimate component (named 'x')
-    type(A), pointer :: potential
+    !ERROR: Allocatable or array component 'potential' may not have a coarray ultimate component '%x'
+    type(A), allocatable :: potential
   end type
 
-
+  type D2
+    !ERROR: Pointer 'potential' may not have a coarray potential component '%x'
+    type(A), pointer :: potential
+  end type
 
   class(*), allocatable :: var
   ! unlimited polymorphic is the ONLY way to get an allocatable/pointer 'var' that can be
diff --git a/flang/test/Semantics/assign02.f90 b/flang/test/Semantics/assign02.f90
index 707d5ed3cfaa55b..a40d204982b2f60 100644
--- a/flang/test/Semantics/assign02.f90
+++ b/flang/test/Semantics/assign02.f90
@@ -74,8 +74,8 @@ subroutine s4(x)
 
   ! C1020
   subroutine s5
-    real, target :: x[*]
-    real, target, volatile :: y[*]
+    real, target, save :: x[*]
+    real, target, volatile, save :: y[*]
     real, pointer :: p
     real, pointer, volatile :: q
     p => x
@@ -148,7 +148,7 @@ function f2()
 
   ! C1026 (R1037) A data-target shall not be a coindexed object.
   subroutine s10
-    real, target :: a[*]
+    real, target, save :: a[*]
     real, pointer :: b
     !ERROR: A coindexed object may not be a pointer target
     b => a[1]
diff --git a/flang/test/Semantics/associated.f90 b/flang/test/Semantics/associated.f90
index 143274480659965..c814980377b9fde 100644
--- a/flang/test/Semantics/associated.f90
+++ b/flang/test/Semantics/associated.f90
@@ -90,7 +90,7 @@ subroutine test(assumedRank)
     type(t2) :: t2x
     type(t2), target :: t2xtarget
     integer, target :: targetIntArr(2)
-    integer, target :: targetIntCoarray[*]
+    integer, target, save :: targetIntCoarray[*]
     integer, pointer :: intPointerArr(:)
     procedure(objPtrFunc), pointer :: objPtrFuncPointer
 
diff --git a/flang/test/Semantics/bind-c09.f90 b/flang/test/Semantics/bind-c09.f90
index 953f2d751234f31..e08e4f001c69610 100644
--- a/flang/test/Semantics/bind-c09.f90
+++ b/flang/test/Semantics/bind-c09.f90
@@ -44,6 +44,6 @@ function func8() result(res) bind(c)
 end
 
 function func9() result(res) bind(c)
-  ! ERROR: Interoperable function result may not be a coarray
+  ! ERROR: Function result may not be a coarray
   integer :: res[10, *]
 end
diff --git a/flang/test/Semantics/call10.f90 b/flang/test/Semantics/call10.f90
index 2d2f57934cd8aa2..81c28082a843fee 100644
--- a/flang/test/Semantics/call10.f90
+++ b/flang/test/Semantics/call10.f90
@@ -200,8 +200,9 @@ pure subroutine s13
     !ERROR: An image control statement may not appear in a pure subprogram
     sync all ! C1599
   end subroutine
-  pure subroutine s14
-    integer :: img, nimgs, i[*], tmp
+  pure subroutine s14(i)
+    integer :: img, nimgs, tmp
+    integer, intent(in out) :: i[*]
                                    ! implicit sync all
     img = this_image()
     nimgs = num_images()
diff --git a/flang/test/Semantics/call12.f90 b/flang/test/Semantics/call12.f90
index 2e5591ad927daf2..cd4006a53b3e75c 100644
--- a/flang/test/Semantics/call12.f90
+++ b/flang/test/Semantics/call12.f90
@@ -40,7 +40,9 @@ pure function test(ptr, in, hpd, hhpd)
     type(hasHiddenPtr), intent(in) :: hhpd
     type(hasPtr), allocatable :: alloc
     type(hasHiddenPtr), allocatable :: hpAlloc
+    !ERROR: Pointer 'hcp' may not have a coarray potential component '%co'
     type(hasCoarray), pointer :: hcp
+    type(hasCoarray), allocatable :: hca
     integer :: n
     common /block/ y
     external :: extfunc
@@ -60,8 +62,8 @@ pure function test(ptr, in, hpd, hhpd)
     !BECAUSE: 'in' is an INTENT(IN) dummy argument
     in%a = 0. ! C1594(1)
     !ERROR: Left-hand side of assignment is not definable
-    !BECAUSE: A pure subprogram may not define the coindexed object 'hcp%co[1_8]'
-    hcp%co[1] = 0. ! C1594(1)
+    !BECAUSE: A pure subprogram may not define the coindexed object 'hca%co[1_8]'
+    hca%co[1] = 0. ! C1594(1)
     !ERROR: The left-hand side of a pointer assignment is not definable
     !BECAUSE: 'ptr' may not be defined in pure subprogram 'test' because it is a POINTER dummy argument of a pure function
     ptr => z ! C1594(2)
diff --git a/flang/test/Semantics/change_team01.f90 b/flang/test/Semantics/change_team01.f90
index 43be1c10fb842b8..a5e53e98fc98687 100644
--- a/flang/test/Semantics/change_team01.f90
+++ b/flang/test/Semantics/change_team01.f90
@@ -4,6 +4,7 @@
 
 subroutine test
   use, intrinsic :: iso_fortran_env, only: team_type
+  save
   type(team_type) :: team
   integer, codimension[*] :: selector
   integer, codimension[2,*] :: selector2d
diff --git a/flang/test/Semantics/coarrays01.f90 b/flang/test/Semantics/coarrays01.f90
index 0a6f88a7e748c90..0dfcd1a41c95dc8 100644
--- a/flang/test/Semantics/coarrays01.f90
+++ b/flang/test/Semantics/coarrays01.f90
@@ -2,7 +2,7 @@
 ! Test selector and team-value in CHANGE TEAM statement
 
 ! OK
-subroutine s1
+subroutine s1(y)
   use iso_fortran_env, only: team_type
   type(team_type) :: t
   real :: y[10,*]
@@ -11,7 +11,7 @@ subroutine s1
   form team(1, t)
 end
 
-subroutine s2
+subroutine s2(y,y2,x)
   use iso_fortran_env
   type(team_type) :: t
   real :: y[10,*], y2[*], x[*]
@@ -27,7 +27,7 @@ subroutine s2
   end team
 end
 
-subroutine s3
+subroutine s3(y)
   type :: team_type
   end type
   type :: foo
diff --git a/flang/test/Semantics/coarrays02.f90 b/flang/test/Semantics/coarrays02.f90
new file mode 100644
index 000000000000000..e52f3e3ef3a406b
--- /dev/null
+++ b/flang/test/Semantics/coarrays02.f90
@@ -0,0 +1,50 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! More coarray error tests.
+module m
+  integer :: local[*] ! ok in module
+end
+program main
+  use iso_fortran_env
+  !ERROR: Coarray 'namedconst' may not be a named constant
+  !ERROR: Local coarray must have the SAVE attribute
+  integer, parameter :: namedConst = 123
+  codimension namedConst[*]
+  !ERROR: Coarray 'coarr1' may not be in COMMON block '//'
+  real :: coarr1[*]
+  common//coarr1
+  !ERROR: Variable 'event' with EVENT_TYPE or LOCK_TYPE must be a coarray
+  type(event_type) event
+  !ERROR: Variable 'lock' with EVENT_TYPE or LOCK_TYPE must be a coarray
+  type(lock_type) lock
+  integer :: local[*] ! ok in main
+end
+
+function func1()
+  !ERROR: Function result may not be a coarray
+  integer :: func1[*]
+  !ERROR: Local coarray must have the SAVE attribute
+  integer :: local[*]
+  integer, save :: saved[*] ! ok
+  integer :: inited[*] = 1 ! ok
+  func = 1
+end
+
+function func2()
+  type t
+    real, allocatable :: comp[:]
+  end type
+  type t2
+    !ERROR: Allocatable or array component 'allo' may not have a coarray ultimate component '%comp'
+    type(t), allocatable :: allo
+    !ERROR: Allocatable or array component 'arr' may not have a coarray ultimate component '%comp'
+    type(t) :: arr(1)
+  end type
+  !ERROR: Function result 'func2' may not have a coarray potential component '%comp'
+  type(t) func2
+  !ERROR: Pointer 'ptr' may not have a coarray potential component '%comp'
+  type(t), pointer :: ptr
+  !ERROR: Coarray 'coarr' may not have a coarray potential component '%comp'
+  type(t), save :: coarr[*]
+  !ERROR: Local variable 'local' without the SAVE attribute may not have a coarray potential subobject component '%comp'
+  type(t) :: local
+end
diff --git a/flang/test/Semantics/critical02.f90 b/flang/test/Semantics/critical02.f90
index 692b06b025861f9..9c957d1e859c55a 100644
--- a/flang/test/Semantics/critical02.f90
+++ b/flang/test/Semantics/critical02.f90
@@ -61,7 +61,7 @@ end subroutine test6
 
 subroutine test7()
   use iso_fortran_env
-  type(event_type) :: x[*], y[*]
+  type(event_type), save :: x[*], y[*]
   critical
     !ERROR: An image control statement is not allowed in a CRITICAL construct
     event post (x)
diff --git a/flang/test/Semantics/doconcurrent01.f90 b/flang/test/Semantics/doconcurrent01.f90
index 9d2c9e1ab3115c6..ab14d970b8501e4 100644
--- a/flang/test/Semantics/doconcurrent01.f90
+++ b/flang/test/Semantics/doconcurrent01.f90
@@ -69,7 ...
[truncated]

@JDPailleux
Copy link
Contributor

LGTM

@klausler klausler merged commit 29025a0 into llvm:main Feb 27, 2025
12 checks passed
@klausler klausler deleted the fix0011 branch February 27, 2025 22:28
cheezeburglar pushed a commit to cheezeburglar/llvm-project that referenced this pull request Feb 28, 2025
Detect and report a bunch of uncaught semantic errors with coarray
declarations. Add more tests, and clean up bad usage in existing tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants