[flang-commits] [flang] [flang] Don't check dummy vs. actual result rank for assumed-rank poi… (PR #66237)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 13 09:46:27 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics
            
<details>
<summary>Changes</summary>
…nters

When associating a function result pointer as an actual argument with a dummy pointer that is assumed-rank, don't emit a bogus error.
--
Full diff: https://github.com/llvm/llvm-project/pull/66237.diff

6 Files Affected:

- (modified) flang/lib/Semantics/check-call.cpp (+6-6) 
- (modified) flang/lib/Semantics/check-declarations.cpp (+2-1) 
- (modified) flang/lib/Semantics/data-to-inits.cpp (+3-2) 
- (modified) flang/lib/Semantics/pointer-assignment.cpp (+19-5) 
- (modified) flang/lib/Semantics/pointer-assignment.h (+3-2) 
- (added) flang/test/Semantics/call39.f90 (+27) 


<pre>
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index c48c382218dc9bb..27abc9e2938af9f 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -329,10 +329,11 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
       typesCompatible = true;
     }
   }
+  bool dummyIsAssumedRank{dummy.type.attrs().test(
+      characteristics::TypeAndShape::Attr::AssumedRank)};
   if (typesCompatible) {
     if (isElemental) {
-    } else if (dummy.type.attrs().test(
-                   characteristics::TypeAndShape::Attr::AssumedRank)) {
+    } else if (dummyIsAssumedRank) {
     } else if (dummy.ignoreTKR.test(common::IgnoreTKR::Rank)) {
     } else if (dummyRank > 0 && !dummyIsAllocatableOrPointer &&
         !dummy.type.attrs().test(
@@ -462,8 +463,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
           : nullptr};
   int actualRank{actualType.Rank()};
   bool actualIsPointer{evaluate::IsObjectPointer(actual, foldingContext)};
-  bool dummyIsAssumedRank{dummy.type.attrs().test(
-      characteristics::TypeAndShape::Attr::AssumedRank)};
   if (dummy.type.attrs().test(
           characteristics::TypeAndShape::Attr::AssumedShape)) {
     // 15.5.2.4(16)
@@ -682,8 +681,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
   if (dummyIsPointer) {
     if (actualIsPointer || dummy.intent == common::Intent::In) {
       if (scope) {
-        semantics::CheckPointerAssignment(
-            context, messages.at(), dummyName, dummy, actual, *scope);
+        semantics::CheckPointerAssignment(context, messages.at(), dummyName,
+            dummy, actual, *scope,
+            /*isAssumedRank=*/dummyIsAssumedRank);
       }
     } else if (!actualIsPointer) {
       messages.Say(
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index e7e091ed024c48d..b22f396643c9b21 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1062,7 +1062,8 @@ void CheckHelper::CheckPointerInitialization(const Symbol &symbol) {
           SomeExpr lhs{evaluate::ProcedureDesignator{symbol}};
           SomeExpr rhs{evaluate::ProcedureDesignator{**proc->init()}};
           CheckPointerAssignment(context_, lhs, rhs,
-              GetProgramUnitOrBlockConstructContaining(symbol));
+              GetProgramUnitOrBlockConstructContaining(symbol),
+              /*isBoundsRemapping=*/false, /*isAssumedRank=*/false);
         }
       }
     }
diff --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index 6fbe044aa4618d4..bc0355a2c597a6f 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -384,8 +384,9 @@ bool DataInitializationCompiler<DSV>::InitElement(
       return true;
     } else if (isProcPointer) {
       if (evaluate::IsProcedure(*expr)) {
-        if (CheckPointerAssignment(
-                exprAnalyzer_.context(), designator, *expr, DEREF(scope_))) {
+        if (CheckPointerAssignment(exprAnalyzer_.context(), designator, *expr,
+                DEREF(scope_),
+                /*isBoundsRemapping=*/false, /*isAssumedRank=*/false)) {
           if (lastSymbol->has<ProcEntityDetails>()) {
             GetImage().AddPointer(offsetSymbol.offset(), *expr);
             return true;
diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp
index e75e9366942115d..8f01a3d7057e196 100644
--- a/flang/lib/Semantics/pointer-assignment.cpp
+++ b/flang/lib/Semantics/pointer-assignment.cpp
@@ -56,6 +56,7 @@ class PointerAssignmentChecker {
   PointerAssignmentChecker &set_isContiguous(bool);
   PointerAssignmentChecker &set_isVolatile(bool);
   PointerAssignmentChecker &set_isBoundsRemapping(bool);
+  PointerAssignmentChecker &set_isAssumedRank(bool);
   PointerAssignmentChecker &set_pointerComponentLHS(const Symbol *);
   bool CheckLeftHandSide(const SomeExpr &);
   bool Check(const SomeExpr &);
@@ -88,6 +89,7 @@ class PointerAssignmentChecker {
   bool isContiguous_{false};
   bool isVolatile_{false};
   bool isBoundsRemapping_{false};
+  bool isAssumedRank_{false};
   const Symbol *pointerComponentLHS_{nullptr};
 };
 
@@ -115,6 +117,12 @@ PointerAssignmentChecker &PointerAssignmentChecker::set_isBoundsRemapping(
   return *this;
 }
 
+PointerAssignmentChecker &PointerAssignmentChecker::set_isAssumedRank(
+    bool isAssumedRank) {
+  isAssumedRank_ = isAssumedRank;
+  return *this;
+}
+
 PointerAssignmentChecker &PointerAssignmentChecker::set_pointerComponentLHS(
     const Symbol *symbol) {
   pointerComponentLHS_ = symbol;
@@ -263,7 +271,7 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
     CHECK(frTypeAndShape);
     if (!lhsType_->IsCompatibleWith(foldingContext_.messages(), *frTypeAndShape,
             "pointer", "function result",
-            isBoundsRemapping_ /*omit shape check*/,
+            /*omitShapeConformanceCheck=*/isBoundsRemapping_ || isAssumedRank_,
             evaluate::CheckConformanceFlags::BothDeferredShape)) {
       return false; // IsCompatibleWith() emitted message
     }
@@ -489,17 +497,20 @@ static bool CheckPointerBounds(
 bool CheckPointerAssignment(SemanticsContext &context,
     const evaluate::Assignment &assignment, const Scope &scope) {
   return CheckPointerAssignment(context, assignment.lhs, assignment.rhs, scope,
-      CheckPointerBounds(context.foldingContext(), assignment));
+      CheckPointerBounds(context.foldingContext(), assignment),
+      /*isAssumedRank=*/false);
 }
 
 bool CheckPointerAssignment(SemanticsContext &context, const SomeExpr &lhs,
-    const SomeExpr &rhs, const Scope &scope, bool isBoundsRemapping) {
+    const SomeExpr &rhs, const Scope &scope, bool isBoundsRemapping,
+    bool isAssumedRank) {
   const Symbol *pointer{GetLastSymbol(lhs)};
   if (!pointer) {
     return false; // error was reported
   }
   PointerAssignmentChecker checker{context, scope, *pointer};
   checker.set_isBoundsRemapping(isBoundsRemapping);
+  checker.set_isAssumedRank(isAssumedRank);
   bool lhsOk{checker.CheckLeftHandSide(lhs)};
   bool rhsOk{checker.Check(rhs)};
   return lhsOk && rhsOk; // don&#x27;t short-circuit
@@ -514,11 +525,12 @@ bool CheckStructConstructorPointerComponent(SemanticsContext &context,
 
 bool CheckPointerAssignment(SemanticsContext &context, parser::CharBlock source,
     const std::string &description, const DummyDataObject &lhs,
-    const SomeExpr &rhs, const Scope &scope) {
+    const SomeExpr &rhs, const Scope &scope, bool isAssumedRank) {
   return PointerAssignmentChecker{context, scope, source, description}
       .set_lhsType(common::Clone(lhs.type))
       .set_isContiguous(lhs.attrs.test(DummyDataObject::Attr::Contiguous))
       .set_isVolatile(lhs.attrs.test(DummyDataObject::Attr::Volatile))
+      .set_isAssumedRank(isAssumedRank)
       .Check(rhs);
 }
 
@@ -526,7 +538,9 @@ bool CheckInitialDataPointerTarget(SemanticsContext &context,
     const SomeExpr &pointer, const SomeExpr &init, const Scope &scope) {
   return evaluate::IsInitialDataTarget(
              init, &context.foldingContext().messages()) &&
-      CheckPointerAssignment(context, pointer, init, scope);
+      CheckPointerAssignment(context, pointer, init, scope,
+          /*isBoundsRemapping=*/false,
+          /*isAssumedRank=*/false);
 }
 
 } // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/pointer-assignment.h b/flang/lib/Semantics/pointer-assignment.h
index 5ac258d03a0a264..269d64112fd29b6 100644
--- a/flang/lib/Semantics/pointer-assignment.h
+++ b/flang/lib/Semantics/pointer-assignment.h
@@ -26,11 +26,12 @@ class Symbol;
 bool CheckPointerAssignment(
     SemanticsContext &, const evaluate::Assignment &, const Scope &);
 bool CheckPointerAssignment(SemanticsContext &, const SomeExpr &lhs,
-    const SomeExpr &rhs, const Scope &, bool isBoundsRemapping = false);
+    const SomeExpr &rhs, const Scope &, bool isBoundsRemapping,
+    bool isAssumedRank);
 bool CheckPointerAssignment(SemanticsContext &, parser::CharBlock source,
     const std::string &description,
     const evaluate::characteristics::DummyDataObject &, const SomeExpr &rhs,
-    const Scope &);
+    const Scope &, bool isAssumedRank);
 
 bool CheckStructConstructorPointerComponent(
     SemanticsContext &, const Symbol &lhs, const SomeExpr &rhs, const Scope &);
diff --git a/flang/test/Semantics/call39.f90 b/flang/test/Semantics/call39.f90
new file mode 100644
index 000000000000000..860ab0096401403
--- /dev/null
+++ b/flang/test/Semantics/call39.f90
@@ -0,0 +1,27 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
+! Tests actual/dummy pointer argument shape mismatches
+module m
+ contains
+  subroutine s0(p)
+    real, pointer, intent(in) :: p
+  end
+  subroutine s1(p)
+    real, pointer, intent(in) :: p(:)
+  end
+  subroutine sa(p)
+    real, pointer, intent(in) :: p(..)
+  end
+  subroutine test
+    real, pointer :: a0, a1(:)
+    call s0(null(a0)) ! ok
+    !ERROR: Rank of dummy argument is 0, but actual argument has rank 1
+    !ERROR: Rank of pointer is 0, but function result has rank 1
+    call s0(null(a1))
+    !ERROR: Rank of dummy argument is 1, but actual argument has rank 0
+    !ERROR: Rank of pointer is 1, but function result has rank 0
+    call s1(null(a0))
+    call s1(null(a1)) ! ok
+    call sa(null(a0)) ! ok
+    call sa(null(a1)) ! ok
+  end
+end
</pre>
</details>


https://github.com/llvm/llvm-project/pull/66237


More information about the flang-commits mailing list