Skip to content

[flang] Do not propagate BIND(C) from main entry to ENTRY #67554

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
Sep 27, 2023

Conversation

jeanPerier
Copy link
Contributor

15.6.2.6 point 11/12/13 tells that entries do inherit the RECURSIVE/PURE/ELEMENTAL aspects from the main entry, but nothing as such is said for BIND(C). It seems each entry can independently have BIND(C) or not.

Update characterization to not propagate this info in-between entries.

Add a lowering test for a tricky case of the character return where the return ABI is different for the result with and without BIND(C), but the results storage should be associated regardless of the ABI.

15.6.2.6 point 11/12/13 tells that entries do inherit the
RECURSIVE/PURE/ELEMENTAL aspects from the main entry, but nothing
as such is said for BIND(C). It seems each entry can independently
have BIND(C) or not.

Update characterization to not propagate this info in-between entries.

Add a lowering test for a tricky case of the character return where the
return ABI is different for the result with and without BIND(C), but
the results storage should be associated regardless of the ABI.
@jeanPerier jeanPerier requested a review from klausler September 27, 2023 13:25
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:semantics labels Sep 27, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 27, 2023

@llvm/pr-subscribers-flang-semantics

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

Changes

15.6.2.6 point 11/12/13 tells that entries do inherit the RECURSIVE/PURE/ELEMENTAL aspects from the main entry, but nothing as such is said for BIND(C). It seems each entry can independently have BIND(C) or not.

Update characterization to not propagate this info in-between entries.

Add a lowering test for a tricky case of the character return where the return ABI is different for the result with and without BIND(C), but the results storage should be associated regardless of the ABI.


Full diff: https://github.com/llvm/llvm-project/pull/67554.diff

2 Files Affected:

  • (modified) flang/lib/Evaluate/characteristics.cpp (+4-1)
  • (added) flang/test/Lower/HLFIR/bindc-entry-stmt.f90 (+70)
diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index 6daa113abe64255..ac61e72f428a97e 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -681,9 +681,12 @@ static std::optional<Procedure> CharacterizeProcedure(
       },
       symbol.details())};
   if (result && !symbol.has<semantics::ProcBindingDetails>()) {
-    CopyAttrs<Procedure, Procedure::Attr>(DEREF(GetMainEntry(&symbol)), *result,
+    CopyAttrs<Procedure, Procedure::Attr>(symbol, *result,
         {
             {semantics::Attr::BIND_C, Procedure::Attr::BindC},
+        });
+    CopyAttrs<Procedure, Procedure::Attr>(DEREF(GetMainEntry(&symbol)), *result,
+        {
             {semantics::Attr::ELEMENTAL, Procedure::Attr::Elemental},
         });
     if (IsPureProcedure(symbol) || // works for ENTRY too
diff --git a/flang/test/Lower/HLFIR/bindc-entry-stmt.f90 b/flang/test/Lower/HLFIR/bindc-entry-stmt.f90
new file mode 100644
index 000000000000000..89e494689e99642
--- /dev/null
+++ b/flang/test/Lower/HLFIR/bindc-entry-stmt.f90
@@ -0,0 +1,70 @@
+! Test that lowering can handle entry statements with character
+! results where some entries are BIND(C) and not the others.
+! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+
+function foo() bind(c)
+  character(1) :: foo, bar
+entry bar()
+  bar = "a"
+end function
+
+! CHECK-LABEL:   func.func @foo() -> !fir.char<1>
+! CHECK:           %[[VAL_0:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_1:.*]] = fir.alloca !fir.char<1> {bindc_name = "foo", uniq_name = "_QFfooEfoo"}
+! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_0]] {uniq_name = "_QFfooEfoo"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           %[[VAL_3:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]]#1 typeparams %[[VAL_3]] {uniq_name = "_QFfooEbar"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           cf.br ^bb1
+! CHECK:         ^bb1:
+! CHECK:           hlfir.assign %{{.*}} to %[[VAL_4]]#0 : !fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>
+! CHECK:           %[[VAL_8:.*]] = fir.load %[[VAL_2]]#1 : !fir.ref<!fir.char<1>>
+! CHECK:           return %[[VAL_8]] : !fir.char<1>
+! CHECK:         }
+!
+! CHECK-LABEL:   func.func @_QPbar(
+! CHECK-SAME:                      %[[VAL_0:.*]]: !fir.ref<!fir.char<1>>,
+! CHECK-SAME:                      %[[VAL_1:.*]]: index) -> !fir.boxchar<1> {
+! CHECK:           %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,?>>
+! CHECK:           %[[VAL_3:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_3]] {uniq_name = "_QFfooEfoo"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK:           %[[VAL_5:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_5]] {uniq_name = "_QFfooEbar"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK:           cf.br ^bb1
+! CHECK:         ^bb1:
+! CHECK:           hlfir.assign %{{.*}} to %[[VAL_6]]#0 : !fir.ref<!fir.char<1>>, !fir.boxchar<1>
+! CHECK:           %[[VAL_10:.*]] = fir.emboxchar %[[VAL_6]]#1, %[[VAL_5]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+! CHECK:           return %[[VAL_10]] : !fir.boxchar<1>
+! CHECK:         }
+
+function foo2()
+  character(1) :: foo2, bar2
+entry bar2() bind(c)
+  bar2 = "a"
+end function
+! CHECK-LABEL:   func.func @_QPfoo2(
+! CHECK-SAME:                       %[[VAL_0:.*]]: !fir.ref<!fir.char<1>>,
+! CHECK-SAME:                       %[[VAL_1:.*]]: index) -> !fir.boxchar<1> {
+! CHECK:           %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,?>>
+! CHECK:           %[[VAL_3:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_3]] {uniq_name = "_QFfoo2Efoo2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK:           %[[VAL_5:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_5]] {uniq_name = "_QFfoo2Ebar2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK:           cf.br ^bb1
+! CHECK:         ^bb1:
+! CHECK:           hlfir.assign %{{.*}} to %[[VAL_6]]#0 : !fir.ref<!fir.char<1>>, !fir.boxchar<1>
+! CHECK:           %[[VAL_10:.*]] = fir.emboxchar %[[VAL_4]]#1, %[[VAL_3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+! CHECK:           return %[[VAL_10]] : !fir.boxchar<1>
+! CHECK:         }
+
+! CHECK-LABEL:   func.func @bar2() -> !fir.char<1>
+! CHECK:           %[[VAL_0:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_1:.*]] = fir.alloca !fir.char<1> {bindc_name = "foo2", uniq_name = "_QFfoo2Efoo2"}
+! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_0]] {uniq_name = "_QFfoo2Efoo2"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           %[[VAL_3:.*]] = arith.constant 1 : index
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]]#1 typeparams %[[VAL_3]] {uniq_name = "_QFfoo2Ebar2"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           cf.br ^bb1
+! CHECK:         ^bb1:
+! CHECK:           hlfir.assign %{{.*}} to %[[VAL_4]]#0 : !fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>
+! CHECK:           %[[VAL_8:.*]] = fir.load %[[VAL_4]]#1 : !fir.ref<!fir.char<1>>
+! CHECK:           return %[[VAL_8]] : !fir.char<1>
+! CHECK:         }

@jeanPerier
Copy link
Contributor Author

@klausler, this propagation was introduced in https://reviews.llvm.org/D159026, I think this may not have been intended, but please correct me if I am wrong here.

@jeanPerier jeanPerier merged commit 09c544e into llvm:main Sep 27, 2023
@jeanPerier jeanPerier deleted the jpr-bindc-entry branch September 27, 2023 17:40
legrosbuffle pushed a commit to legrosbuffle/llvm-project that referenced this pull request Sep 29, 2023
15.6.2.6 point 11/12/13 tells that entries do inherit the
RECURSIVE/PURE/ELEMENTAL aspects from the main entry, but nothing as
such is said for BIND(C). It seems each entry can independently have
BIND(C) or not.

Update characterization to not propagate this info in-between entries.

Add a lowering test for a tricky case of the character return where the
return ABI is different for the result with and without BIND(C), but the
results storage should be associated regardless of the ABI.
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.

3 participants