[flang-commits] [flang] [flang] Add dummy intent attribute to the function signature (PR #229237)

Susan Tan ス-ザン タン via flang-commits flang-commits at lists.llvm.org
Mon Oct 5 15:04:04 PDT 2026


https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/229237

>From 0a0fbc32b64e8d23d08312a87e3317c38b77ce81 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Mon, 5 Oct 2026 14:34:27 -0700
Subject: [PATCH 1/4] add intent attribute

---
 .../flang/Optimizer/Dialect/FIROpsSupport.h   | 47 ++++++++++--------
 flang/lib/Lower/CallInterface.cpp             | 46 +++++++++++++++--
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  8 +--
 .../AliasAnalysis/modref-call-intent.fir      | 49 ++++++++++++++++---
 flang/test/Driver/function-attr-readonly.f90  | 10 ++--
 .../Lower/dummy-argument-attrs-module.f90     |  8 +++
 flang/test/Lower/dummy-argument-attrs-use.f90 | 16 ++++++
 flang/test/Lower/dummy-argument-readonly.f90  | 48 +++++++++---------
 flang/test/Lower/volatile1.f90                |  6 +--
 9 files changed, 171 insertions(+), 67 deletions(-)
 create mode 100644 flang/test/Lower/dummy-argument-attrs-module.f90
 create mode 100644 flang/test/Lower/dummy-argument-attrs-use.f90

diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index 1fa01bdfc9e88..d30f332406a7f 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -109,6 +109,14 @@ static constexpr llvm::StringRef getReadOnlyAttrName() {
   return "fir.read_only";
 }
 
+/// Dummy intent, attached to the corresponding `func.func` argument.
+/// A function pass reads intent from this signature attribute and does not
+/// inspect another function's body. The `fir.` prefix is required: function
+/// arguments may only carry dialect attributes.
+static constexpr llvm::StringRef getFortranAttrsAttrName() {
+  return "fir.fortran_attrs";
+}
+
 /// Attribute to mark that a function argument is a character dummy procedure.
 /// Character dummy procedure have special ABI constraints.
 static constexpr llvm::StringRef getCharacterProcedureDummyAttrName() {
@@ -240,35 +248,32 @@ inline mlir::NamedAttribute getAdaptToByRefAttr(Builder &builder) {
 
 bool isDummyArgument(mlir::Value v);
 
-/// Intent of dummy argument `argIdx` when `callee`'s body declares it.
-/// Empty when the body is missing or the dummy has no intent attribute.
+/// Intent of function argument `argIdx`.
 enum class FortranDummyIntent { In, Out, InOut };
 
+/// Intent recorded by the `fortran_attrs` attribute of argument `argIdx`.
+/// Empty when that attribute is absent or names no intent. The callee region
+/// is not inspected: a function pass may query another function only through
+/// its signature.
 inline std::optional<FortranDummyIntent>
 getFortranDummyIntent(mlir::func::FuncOp callee, unsigned argIdx) {
   if (!callee || argIdx >= callee.getNumArguments())
     return std::nullopt;
-  // The dummy's fir.declare uses the block argument as its memref.
-  mlir::Value arg = callee.getArgument(argIdx);
-  for (mlir::Operation *user : arg.getUsers()) {
-    auto decl = mlir::dyn_cast<fir::DeclareOp>(user);
-    if (!decl || decl.getMemref() != arg)
-      continue;
-    auto attrs = decl.getFortranAttrs();
-    if (!attrs)
-      continue;
-    using F = FortranVariableFlagsEnum;
-    if (bitEnumContainsAny(*attrs, F::intent_inout) ||
-        (bitEnumContainsAny(*attrs, F::intent_in) &&
-         bitEnumContainsAny(*attrs, F::intent_out)))
-      return FortranDummyIntent::InOut;
-    if (bitEnumContainsAny(*attrs, F::intent_out))
-      return FortranDummyIntent::Out;
-    if (bitEnumContainsAny(*attrs, F::intent_in))
-      return FortranDummyIntent::In;
+  auto attrs = callee.getArgAttrOfType<FortranVariableFlagsAttr>(
+      argIdx, getFortranAttrsAttrName());
+  if (!attrs)
+    return std::nullopt;
+  using F = FortranVariableFlagsEnum;
+  switch (attrs.getFlags() & (F::intent_in | F::intent_out | F::intent_inout)) {
+  case F::intent_in:
+    return FortranDummyIntent::In;
+  case F::intent_out:
+    return FortranDummyIntent::Out;
+  case F::intent_inout:
+    return FortranDummyIntent::InOut;
+  default:
     return std::nullopt;
   }
-  return std::nullopt;
 }
 
 template <fir::FortranProcedureFlagsEnum Flag>
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 2bfe94559cd88..ee6ee38f165f9 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -252,6 +252,36 @@ static bool dummyArgCanUseLLVMReadonly(
          !obj.attrs.test(Attrs::Volatile);
 }
 
+/// Intent of a dummy, recorded on the procedure signature. Both the definition
+/// and a caller-created declaration see this, so intent is available without
+/// the callee body. Other dummy flags stay on their existing attributes.
+static fir::FortranVariableFlagsEnum getDummyIntentFlags(
+    const Fortran::evaluate::characteristics::DummyDataObject &obj) {
+  switch (obj.intent) {
+  case Fortran::common::Intent::In:
+    return fir::FortranVariableFlagsEnum::intent_in;
+  case Fortran::common::Intent::Out:
+    return fir::FortranVariableFlagsEnum::intent_out;
+  case Fortran::common::Intent::InOut:
+    return fir::FortranVariableFlagsEnum::intent_inout;
+  case Fortran::common::Intent::Default:
+    return fir::FortranVariableFlagsEnum::None;
+  }
+  llvm_unreachable("unhandled dummy intent");
+}
+
+static void addFortranVariableFlagsAttr(
+    llvm::SmallVectorImpl<mlir::NamedAttribute> &attrs,
+    mlir::MLIRContext &mlirContext,
+    const Fortran::evaluate::characteristics::DummyDataObject &obj) {
+  fir::FortranVariableFlagsEnum flags = getDummyIntentFlags(obj);
+  if (flags == fir::FortranVariableFlagsEnum::None)
+    return;
+  attrs.emplace_back(
+      mlir::StringAttr::get(&mlirContext, fir::getFortranAttrsAttrName()),
+      fir::FortranVariableFlagsAttr::get(&mlirContext, flags));
+}
+
 static Fortran::evaluate::characteristics::DummyArgument
 asImplicitArg(Fortran::evaluate::characteristics::DummyArgument &&dummy) {
   return Fortran::common::visit(
@@ -1138,15 +1168,18 @@ class Fortran::lower::CallInterfaceImpl {
       if (entity) {
         if (entity->isPercentVal()) {
           mlir::Type type = translateDynamicType(dynamicType);
-          addFirOperand(type, nextPassedArgPosition(), Property::Value,
-                        dummyNameAttr(entity));
+          llvm::SmallVector<mlir::NamedAttribute> attrs = dummyNameAttr(entity);
+          addFortranVariableFlagsAttr(attrs, mlirContext, obj);
+          addFirOperand(type, nextPassedArgPosition(), Property::Value, attrs);
           addPassedArg(PassEntityBy::Value, entity, characteristics);
           return;
         }
         if (entity->isPercentRef()) {
           mlir::Type refType = getRefType(dynamicType, obj);
+          llvm::SmallVector<mlir::NamedAttribute> attrs = dummyNameAttr(entity);
+          addFortranVariableFlagsAttr(attrs, mlirContext, obj);
           addFirOperand(refType, nextPassedArgPosition(), Property::BaseAddress,
-                        dummyNameAttr(entity));
+                        attrs);
           addPassedArg(PassEntityBy::BaseAddress, entity, characteristics);
           return;
         }
@@ -1155,8 +1188,10 @@ class Fortran::lower::CallInterfaceImpl {
     if (dynamicType.category() == Fortran::common::TypeCategory::Character) {
       mlir::Type boxCharTy =
           fir::BoxCharType::get(&mlirContext, dynamicType.kind());
+      llvm::SmallVector<mlir::NamedAttribute> attrs = dummyNameAttr(entity);
+      addFortranVariableFlagsAttr(attrs, mlirContext, obj);
       addFirOperand(boxCharTy, nextPassedArgPosition(), Property::BoxChar,
-                    dummyNameAttr(entity));
+                    attrs);
       addPassedArg(PassEntityBy::BoxChar, entity, characteristics);
     } else {
       // non-PDT derived type allowed in implicit interface.
@@ -1168,6 +1203,7 @@ class Fortran::lower::CallInterfaceImpl {
         attrs.emplace_back(
             mlir::StringAttr::get(&mlirContext, fir::getReadOnlyAttrName()),
             mlir::UnitAttr::get(&mlirContext));
+      addFortranVariableFlagsAttr(attrs, mlirContext, obj);
       addFirOperand(refType, nextPassedArgPosition(), Property::BaseAddress,
                     attrs);
       addPassedArg(PassEntityBy::BaseAddress, entity, characteristics);
@@ -1232,6 +1268,8 @@ class Fortran::lower::CallInterfaceImpl {
     // (see dummyArgCanUseLLVMReadonly).
     if (dummyArgCanUseLLVMReadonly(obj))
       addMLIRAttr(fir::getReadOnlyAttrName());
+    // Intent only. The unit attributes above stay as they are.
+    addFortranVariableFlagsAttr(attrs, mlirContext, obj);
 
     // TODO: intents that require special care (e.g finalization)
 
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 94e3726d6228a..1e83828594e6e 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -1135,7 +1135,9 @@ ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
   // declared intent is a read, a write, or both. intent(out) is a write for
   // a trivial non-pointer, non-allocatable dummy, and a read and a write
   // otherwise. An argument with no visible intent stays ModAndRef. The
-  // callee is resolved through the cached symbol table.
+  // callee is resolved through the cached symbol table. Intent is a
+  // signature attribute, so a declaration is enough and the callee body is
+  // not inspected.
   mlir::func::FuncOp callee;
   if (std::optional<mlir::SymbolRefAttr> calleeAttr = call.getCallee()) {
     if (const mlir::SymbolTable *symTab = getNearestSymbolTable(call))
@@ -1143,8 +1145,8 @@ ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
           symTab->lookup<mlir::func::FuncOp>(calleeAttr->getLeafReference());
   }
   auto args = call.getArgs();
-  const bool intentsAvailable = callee && !callee.isDeclaration() &&
-                                args.size() == callee.getNumArguments();
+  const bool intentsAvailable =
+      callee && args.size() == callee.getNumArguments();
   ModRefResult modRef = ModRefResult::getNoModRef();
   for (auto [idx, arg] : llvm::enumerate(args)) {
     if (!fir::conformsWithPassByRef(arg.getType()) || alias(arg, var).isNo())
diff --git a/flang/test/Analysis/AliasAnalysis/modref-call-intent.fir b/flang/test/Analysis/AliasAnalysis/modref-call-intent.fir
index 176769c7cdb4f..54b64763da722 100644
--- a/flang/test/Analysis/AliasAnalysis/modref-call-intent.fir
+++ b/flang/test/Analysis/AliasAnalysis/modref-call-intent.fir
@@ -2,7 +2,9 @@
 // RUN:  --mlir-disable-threading %s -o /dev/null 2>&1 | FileCheck %s
 
 // A direct call uses the callee dummy's Fortran intent when the argument
-// aliases the queried variable:
+// aliases the queried variable. Intent is the fortran_attrs attribute on the
+// func.func argument. A fir.declare in the callee body is not consulted, so
+// the same result holds for a declaration with no body.
 //   intent(in)    -> Ref
 //   intent(out)   -> Mod for a trivial non-pointer, non-allocatable dummy
 //   intent(out)   -> ModRef for an allocatable or a derived type
@@ -27,6 +29,12 @@
 // CHECK-DAG: alloc_out_call -> other#0: NoModRef{{$}}
 // CHECK-DAG: derived_out_call -> derived_out#0: ModRef{{$}}
 // CHECK-DAG: derived_out_call -> other#0: NoModRef{{$}}
+// CHECK-DAG: decl_out_call -> decl_out#0: Mod{{$}}
+// CHECK-DAG: decl_out_call -> other#0: NoModRef{{$}}
+// CHECK-DAG: body_only_call -> body_only#0: ModRef{{$}}
+// CHECK-DAG: body_only_call -> other#0: NoModRef{{$}}
+// CHECK-DAG: sig_wins_call -> sig_wins#0: Ref{{$}}
+// CHECK-DAG: sig_wins_call -> other#0: NoModRef{{$}}
 func.func @test_call_intent() {
   %in_alloca = fir.alloca f32 {bindc_name = "in", uniq_name = "_QFtest_call_intentEin"}
   %in = fir.declare %in_alloca uniq_name("_QFtest_call_intentEin") {test.ptr = "in"} : (!fir.ref<f32>) -> !fir.ref<f32>
@@ -52,20 +60,32 @@ func.func @test_call_intent() {
   %derived_out_alloca = fir.alloca !fir.type<_QTdt{i:i32}> {bindc_name = "derived_out", uniq_name = "_QFtest_call_intentEderived_out"}
   %derived_out = fir.declare %derived_out_alloca uniq_name("_QFtest_call_intentEderived_out") {test.ptr = "derived_out"} : (!fir.ref<!fir.type<_QTdt{i:i32}>>) -> !fir.ref<!fir.type<_QTdt{i:i32}>>
   fir.call @_QPfill_derived_out(%derived_out) {test.ptr = "derived_out_call"} : (!fir.ref<!fir.type<_QTdt{i:i32}>>) -> ()
+
+  %decl_out_alloca = fir.alloca f32 {bindc_name = "decl_out", uniq_name = "_QFtest_call_intentEdecl_out"}
+  %decl_out = fir.declare %decl_out_alloca uniq_name("_QFtest_call_intentEdecl_out") {test.ptr = "decl_out"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  fir.call @_QPfill_out_decl(%decl_out) {test.ptr = "decl_out_call"} : (!fir.ref<f32>) -> ()
+
+  %body_only_alloca = fir.alloca f32 {bindc_name = "body_only", uniq_name = "_QFtest_call_intentEbody_only"}
+  %body_only = fir.declare %body_only_alloca uniq_name("_QFtest_call_intentEbody_only") {test.ptr = "body_only"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  fir.call @_QPbody_only_out(%body_only) {test.ptr = "body_only_call"} : (!fir.ref<f32>) -> ()
+
+  %sig_wins_alloca = fir.alloca f32 {bindc_name = "sig_wins", uniq_name = "_QFtest_call_intentEsig_wins"}
+  %sig_wins = fir.declare %sig_wins_alloca uniq_name("_QFtest_call_intentEsig_wins") {test.ptr = "sig_wins"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  fir.call @_QPsig_in_body_out(%sig_wins) {test.ptr = "sig_wins_call"} : (!fir.ref<f32>) -> ()
   return
 }
 
-func.func private @_QPread_in(%arg0: !fir.ref<f32>) {
+func.func private @_QPread_in(%arg0: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
   %x = fir.declare %arg0 uniq_name("_QFread_inEx") fortran_attrs<intent_in> : (!fir.ref<f32>) -> !fir.ref<f32>
   return
 }
 
-func.func private @_QPfill_out(%arg0: !fir.ref<f32>) {
+func.func private @_QPfill_out(%arg0: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
   %x = fir.declare %arg0 uniq_name("_QFfill_outEx") fortran_attrs<intent_out> : (!fir.ref<f32>) -> !fir.ref<f32>
   return
 }
 
-func.func private @_QPupdate_inout(%arg0: !fir.ref<f32>) {
+func.func private @_QPupdate_inout(%arg0: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
   %x = fir.declare %arg0 uniq_name("_QFupdate_inoutEx") fortran_attrs<intent_inout> : (!fir.ref<f32>) -> !fir.ref<f32>
   return
 }
@@ -75,19 +95,34 @@ func.func private @_QPno_intent(%arg0: !fir.ref<f32>) {
   return
 }
 
-func.func private @_QPscratch(%arg0: !fir.ref<f32>, %arg1: !fir.ref<f32>, %arg2: !fir.ref<f32>) {
+func.func private @_QPscratch(%arg0: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_in>}, %arg1: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %arg2: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
   %x = fir.declare %arg0 uniq_name("_QFscratchEx") fortran_attrs<intent_in> : (!fir.ref<f32>) -> !fir.ref<f32>
   %a = fir.declare %arg1 uniq_name("_QFscratchEa") fortran_attrs<intent_inout> : (!fir.ref<f32>) -> !fir.ref<f32>
   %res = fir.declare %arg2 uniq_name("_QFscratchEres") fortran_attrs<intent_out> : (!fir.ref<f32>) -> !fir.ref<f32>
   return
 }
 
-func.func private @_QPfill_alloc_out(%arg0: !fir.ref<!fir.box<!fir.heap<f32>>>) {
+func.func private @_QPfill_alloc_out(%arg0: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
   %x = fir.declare %arg0 uniq_name("_QFfill_alloc_outEx") fortran_attrs<allocatable, intent_out> : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>>
   return
 }
 
-func.func private @_QPfill_derived_out(%arg0: !fir.ref<!fir.type<_QTdt{i:i32}>>) {
+func.func private @_QPfill_derived_out(%arg0: !fir.ref<!fir.type<_QTdt{i:i32}>> {fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
   %x = fir.declare %arg0 uniq_name("_QFfill_derived_outEx") fortran_attrs<intent_out> : (!fir.ref<!fir.type<_QTdt{i:i32}>>) -> !fir.ref<!fir.type<_QTdt{i:i32}>>
   return
 }
+
+// No body: the signature attribute is the only place intent can live.
+func.func private @_QPfill_out_decl(!fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_out>})
+
+// Intent on the declare only. It must not be visible across functions.
+func.func private @_QPbody_only_out(%arg0: !fir.ref<f32>) {
+  %x = fir.declare %arg0 uniq_name("_QFbody_only_outEx") fortran_attrs<intent_out> : (!fir.ref<f32>) -> !fir.ref<f32>
+  return
+}
+
+// The signature wins when it disagrees with the declare in the body.
+func.func private @_QPsig_in_body_out(%arg0: !fir.ref<f32> {fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
+  %x = fir.declare %arg0 uniq_name("_QFsig_in_body_outEx") fortran_attrs<intent_out> : (!fir.ref<f32>) -> !fir.ref<f32>
+  return
+}
diff --git a/flang/test/Driver/function-attr-readonly.f90 b/flang/test/Driver/function-attr-readonly.f90
index 120fa8f266da5..5345a12a09975 100644
--- a/flang/test/Driver/function-attr-readonly.f90
+++ b/flang/test/Driver/function-attr-readonly.f90
@@ -31,17 +31,17 @@ subroutine pointer_descriptor_readonly(p)
 end module
 
 ! O0-LABEL: func.func @_QMreadonly_pipeline_modPreadonly_pipeline(
-! O0-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only, llvm.noalias},
-! O0-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "y", llvm.noalias})
+! O0-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only, llvm.noalias},
+! O0-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_inout>, llvm.noalias})
 
 ! O1-LABEL: func.func @_QMreadonly_pipeline_modPreadonly_pipeline(
-! O1-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only, llvm.noalias, llvm.nocapture, llvm.readonly},
-! O1-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "y", llvm.noalias, llvm.nocapture})
+! O1-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only, llvm.noalias, llvm.nocapture, llvm.readonly},
+! O1-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_inout>, llvm.noalias, llvm.nocapture})
 
 ! LLVM-LABEL: define void @_QMreadonly_pipeline_modPreadonly_pipeline(
 ! LLVM-SAME:    ptr {{.*}}readonly{{.*}} %0,
 
-! O1-LABEL: func.func @_QMreadonly_pipeline_modPpointer_descriptor_readonly(%{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "p", fir.read_only, llvm.nocapture, llvm.readonly})
+! O1-LABEL: func.func @_QMreadonly_pipeline_modPpointer_descriptor_readonly(%{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only, llvm.nocapture, llvm.readonly})
 
 ! LLVM-LABEL: define void @_QMreadonly_pipeline_modPpointer_descriptor_readonly(
 ! LLVM-SAME:    ptr {{.*}}readonly{{.*}} %0
diff --git a/flang/test/Lower/dummy-argument-attrs-module.f90 b/flang/test/Lower/dummy-argument-attrs-module.f90
new file mode 100644
index 0000000000000..ed0d295f4d60c
--- /dev/null
+++ b/flang/test/Lower/dummy-argument-attrs-module.f90
@@ -0,0 +1,8 @@
+module m
+contains
+  subroutine twice(x, y)
+    double precision, intent(in) :: x
+    double precision, intent(out) :: y
+    y = 2 * x
+  end subroutine twice
+end module m
diff --git a/flang/test/Lower/dummy-argument-attrs-use.f90 b/flang/test/Lower/dummy-argument-attrs-use.f90
new file mode 100644
index 0000000000000..d83b51998a5bc
--- /dev/null
+++ b/flang/test/Lower/dummy-argument-attrs-use.f90
@@ -0,0 +1,16 @@
+! The caller only has the module interface. Intent must still appear on the
+! private func.func declaration, with no callee body to inspect.
+!
+! RUN: rm -fr %t && mkdir -p %t && cd %t
+! RUN: bbc -emit-hlfir %S/dummy-argument-attrs-module.f90
+! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+
+program p
+  use m
+  implicit none
+  double precision :: a, b
+  a = 1.0d0
+  call twice(a, b)
+end program p
+
+! CHECK: func.func private @_QMmPtwice(!fir.ref<f64> {fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, !fir.ref<f64> {fir.fortran_attrs = #fir.var_attrs<intent_out>})
diff --git a/flang/test/Lower/dummy-argument-readonly.f90 b/flang/test/Lower/dummy-argument-readonly.f90
index 97ae5bea85227..6e0b21b41be68 100644
--- a/flang/test/Lower/dummy-argument-readonly.f90
+++ b/flang/test/Lower/dummy-argument-readonly.f90
@@ -8,51 +8,51 @@ subroutine scalar_intent_in(x)
   integer, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine real_scalar_intent_in(x)
   real, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPreal_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<f32> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<f32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine complex_scalar_intent_in(x)
   complex, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPcomplex_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<complex<f32>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<complex<f32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine logical_scalar_intent_in(x)
   logical, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPlogical_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 recursive subroutine recursive_scalar_intent_in(x)
   integer, intent(in) :: x
   if (x > 0) call recursive_scalar_intent_in(x - 1)
 end subroutine
 ! CHECK-LABEL: func.func @_QPrecursive_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only}) attributes
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) attributes
 
 subroutine optional_scalar_intent_in(x)
   integer, intent(in), optional :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPoptional_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.optional, fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.optional, fir.read_only}) {
 
 subroutine target_scalar_intent_in(x)
   integer, intent(in), target :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPtarget_scalar_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only, fir.target}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only, fir.target}) {
 
 subroutine bindc_definition_intent_in(x) bind(c)
   use iso_c_binding, only : c_int
   integer(c_int), intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @bindc_definition_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.read_only}) attributes
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) attributes
 
 ! Arrays are excluded because a forwarded dummy without an INTENT contract may
 ! require compiler-generated copy-out.
@@ -60,38 +60,38 @@ subroutine explicit_shape_intent_in(x)
   integer, intent(in) :: x(10)
 end subroutine
 ! CHECK-LABEL: func.func @_QPexplicit_shape_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 subroutine assumed_size_intent_in(x)
   integer, intent(in) :: x(*)
 end subroutine
 ! CHECK-LABEL: func.func @_QPassumed_size_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 subroutine target_explicit_shape_intent_in(x)
   integer, intent(in), target :: x(10)
 end subroutine
 ! CHECK-LABEL: func.func @_QPtarget_explicit_shape_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x", fir.target}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.target}) {
 
 subroutine assumed_shape_intent_in(x)
   integer, intent(in) :: x(:)
 end subroutine
 ! CHECK-LABEL: func.func @_QPassumed_shape_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 subroutine assumed_rank_intent_in(x)
   integer, intent(in) :: x(..)
 end subroutine
 ! CHECK-LABEL: func.func @_QPassumed_rank_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.box<!fir.array<*:i32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.box<!fir.array<*:i32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 ! CHARACTER and derived types are outside the current conservative subset.
 subroutine character_intent_in(x)
   character(len=*), intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPcharacter_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.boxchar<1> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.boxchar<1> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 module readonly_derived_types
   type :: type_with_array
@@ -102,20 +102,20 @@ subroutine derived_with_array_intent_in(x)
     type(type_with_array), intent(in) :: x
   end subroutine
 ! CHECK-LABEL: func.func @_QMreadonly_derived_typesPderived_with_array_intent_in(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.type<{{.*}}>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.type<{{.*}}>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 end module
 
 subroutine intent_inout(x)
   integer, intent(inout) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_inout(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 
 subroutine intent_out(x)
   integer, intent(out) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_out(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 
 subroutine intent_unspecified(x)
   integer :: x
@@ -127,31 +127,31 @@ subroutine intent_in_value(x)
   integer, intent(in), value :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_value(
-! CHECK-SAME:    %{{.*}}: i32 {fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: i32 {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 subroutine intent_in_pointer(x)
   integer, intent(in), pointer :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_pointer(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine intent_in_allocatable(x)
   integer, intent(in), allocatable :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_allocatable(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.heap<i32>>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.heap<i32>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine intent_in_pointer_array(x)
   integer, intent(in), pointer :: x(:)
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_pointer_array(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 subroutine intent_in_allocatable_array(x)
   integer, intent(in), allocatable :: x(:)
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_allocatable_array(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 
 ! The marker is shallow for descriptor arguments. Defining a POINTER target is
 ! valid even though the descriptor itself has INTENT(IN).
@@ -160,14 +160,14 @@ subroutine intent_in_pointer_target_write(x)
   x = 42
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_pointer_target_write(
-! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "x", fir.read_only}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK:         hlfir.assign {{.*}} to {{.*}} : i32, !fir.ptr<i32>
 
 subroutine intent_in_asynchronous(x)
   integer, intent(in), asynchronous :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPintent_in_asynchronous(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.asynchronous, fir.bindc_name = "x"}) {
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.asynchronous, fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 
 ! VOLATILE with INTENT(IN) is prohibited by C870 (Fortran 2023) and is already
 ! covered by test/Semantics/misc-declarations.f90, so it cannot be exercised by
diff --git a/flang/test/Lower/volatile1.f90 b/flang/test/Lower/volatile1.f90
index 98e88662e59aa..e7f91edb255b1 100644
--- a/flang/test/Lower/volatile1.f90
+++ b/flang/test/Lower/volatile1.f90
@@ -66,7 +66,7 @@ subroutine declared_volatile_in_this_scope(v,n)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func private @_QFPnot_declared_volatile_in_this_scope(
-! CHECK-SAME:                                                               %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "v"}) attributes {{.+}} {
+! CHECK-SAME:                                                               %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "v", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) attributes {{.+}} {
 ! CHECK:           %[[VAL_1:.*]] = arith.constant 1 : i32
 ! CHECK:           %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {{.+}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
@@ -75,8 +75,8 @@ subroutine declared_volatile_in_this_scope(v,n)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func private @_QFPdeclared_volatile_in_this_scope(
-! CHECK-SAME:                                                           %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "v"},
-! CHECK-SAME:                                                           %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "n", fir.read_only}) attributes {{.+}} {
+! CHECK-SAME:                                                           %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "v", fir.fortran_attrs = #fir.var_attrs<intent_inout>},
+! CHECK-SAME:                                                           %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "n", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) attributes {{.+}} {
 ! CHECK:           %[[VAL_2:.*]] = arith.constant 1 : i32
 ! CHECK:           %[[VAL_3:.*]] = arith.constant 0 : index
 ! CHECK:           %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope

>From adb4b1bc9ba38846c9218a60210ec47e6798ae79 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Mon, 5 Oct 2026 14:40:06 -0700
Subject: [PATCH 2/4] tweak

---
 flang/lib/Optimizer/Analysis/AliasAnalysis.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 1e83828594e6e..9e568af786910 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -1165,7 +1165,9 @@ ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
       // A pure write only for a non-pointer, non-allocatable dummy whose
       // element type is trivial. An allocatable is read on entry so it can
       // be deallocated, and finalization of a derived type may read it.
-      mlir::Type ty = callee.getArgument(idx).getType();
+      // Use the function type: a declaration has no entry block, so
+      // getArgument() is not available.
+      mlir::Type ty = callee.getFunctionType().getInput(idx);
       if (fir::isPointerType(ty) || fir::isAllocatableType(ty) ||
           !fir::isa_trivial(fir::getFortranElementType(ty)))
         return ModRefResult::getModAndRef();

>From 8348d87ec398286f5579d5c5ef180db2d2d5acaf Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Mon, 5 Oct 2026 14:42:39 -0700
Subject: [PATCH 3/4] tweak

---
 flang/include/flang/Optimizer/Dialect/FIROpsSupport.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index d30f332406a7f..d5131500ecbbd 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -263,13 +263,12 @@ getFortranDummyIntent(mlir::func::FuncOp callee, unsigned argIdx) {
       argIdx, getFortranAttrsAttrName());
   if (!attrs)
     return std::nullopt;
-  using F = FortranVariableFlagsEnum;
-  switch (attrs.getFlags() & (F::intent_in | F::intent_out | F::intent_inout)) {
-  case F::intent_in:
+  switch (attrs.getFlags()) {
+  case FortranVariableFlagsEnum::intent_in:
     return FortranDummyIntent::In;
-  case F::intent_out:
+  case FortranVariableFlagsEnum::intent_out:
     return FortranDummyIntent::Out;
-  case F::intent_inout:
+  case FortranVariableFlagsEnum::intent_inout:
     return FortranDummyIntent::InOut;
   default:
     return std::nullopt;

>From 973191980c9270344d397b460dda4476f00d1a64 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Mon, 5 Oct 2026 15:03:38 -0700
Subject: [PATCH 4/4] tests

---
 flang/test/Lower/CUDA/cuda-gpu-managed.cuf    |  2 +-
 .../Lower/CUDA/cuf-defined-assignment-rhs.cuf |  2 +-
 .../HLFIR/convert-variable-assumed-rank.f90   | 14 ++---
 .../test/Lower/HLFIR/elemental-array-ops.f90  | 12 ++---
 .../HLFIR/elemental-polymorphic-merge.f90     |  4 +-
 .../Lower/HLFIR/elemental-result-length.f90   |  4 +-
 .../Lower/HLFIR/structure-constructor.f90     |  2 +-
 .../test/Lower/Intrinsics/c_devptr_eq_ne.f90  |  4 +-
 flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90   |  4 +-
 flang/test/Lower/Intrinsics/dconjg.f90        |  4 +-
 flang/test/Lower/Intrinsics/dimag.f90         |  4 +-
 flang/test/Lower/Intrinsics/dreal.f90         |  4 +-
 flang/test/Lower/Intrinsics/perror.f90        |  2 +-
 flang/test/Lower/Intrinsics/reduce.f90        |  2 +-
 flang/test/Lower/OpenACC/acc-declare.f90      |  4 +-
 flang/test/Lower/OpenMP/array-bounds.f90      |  4 +-
 flang/test/Lower/OpenMP/flush.f90             |  4 +-
 .../Lower/OpenMP/optional-argument-map-2.f90  |  4 +-
 .../Lower/OpenMP/optional-argument-map-3.f90  |  2 +-
 .../Lower/OpenMP/optional-argument-map.f90    |  4 +-
 flang/test/Lower/OpenMP/single.f90            |  8 +--
 .../wsloop-reduction-array-assumed-shape.f90  |  2 +-
 .../test/Lower/OpenMP/wsloop-unstructured.f90 |  8 +--
 flang/test/Lower/achar.f90                    |  2 +-
 flang/test/Lower/arguments.f90                |  4 +-
 .../array-elemental-calls-char-dynamic.f90    |  4 +-
 flang/test/Lower/call-copy-in-out.f90         |  6 +--
 flang/test/Lower/default-initialization.f90   |  2 +-
 .../test/Lower/derived-type-finalization.f90  |  4 +-
 flang/test/Lower/dispatch.f90                 |  4 +-
 flang/test/Lower/intentout-deallocate.f90     | 18 +++----
 flang/test/Lower/parent-component.f90         |  4 +-
 flang/test/Lower/polymorphic-temp.f90         | 24 ++++-----
 flang/test/Lower/polymorphic.f90              | 52 +++++++++----------
 .../Lower/repack-arrays-finalized-dummy.f90   |  2 +-
 flang/test/Lower/repack-arrays.f90            |  6 +--
 flang/test/Lower/select-type-2.f90            |  2 +-
 flang/test/Lower/select-type.f90              | 20 +++----
 flang/test/Lower/unsigned-ops.f90             |  4 +-
 flang/test/Lower/volatile-string.f90          |  4 +-
 40 files changed, 133 insertions(+), 133 deletions(-)

diff --git a/flang/test/Lower/CUDA/cuda-gpu-managed.cuf b/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
index 2f26262878abd..c20a85867b6a6 100644
--- a/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
+++ b/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
@@ -179,7 +179,7 @@ subroutine test_dummy_allocatable(arr)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtest_dummy_allocatable(
-! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {cuf.data_attr = #cuf.cuda<managed>, fir.bindc_name = "arr"})
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {cuf.data_attr = #cuf.cuda<managed>, fir.bindc_name = "arr", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 ! CHECK: hlfir.declare {{.*}} {{.*}}fortran_attrs<allocatable, intent_inout> data_attr(#cuf.cuda<managed>)
 
 ! -----------------------------------------------------------------------------
diff --git a/flang/test/Lower/CUDA/cuf-defined-assignment-rhs.cuf b/flang/test/Lower/CUDA/cuf-defined-assignment-rhs.cuf
index 855e2ef34fa4f..8ca6e71752f48 100644
--- a/flang/test/Lower/CUDA/cuf-defined-assignment-rhs.cuf
+++ b/flang/test/Lower/CUDA/cuf-defined-assignment-rhs.cuf
@@ -20,7 +20,7 @@ contains
 end module
 
 ! CHECK-LABEL: func.func @_QMdefined_assignment_device_rhsPassign_t(
-! CHECK-SAME: %[[HOST_T_ARG:.*]]: !fir.ref<!fir.type<_QMdefined_assignment_device_rhsTt{{.*}}> {{.*}}, %[[DEV_X_ARG:.*]]: !fir.box<!fir.array<?xf32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "dev_x"})
+! CHECK-SAME: %[[HOST_T_ARG:.*]]: !fir.ref<!fir.type<_QMdefined_assignment_device_rhsTt{{.*}}> {{.*}}, %[[DEV_X_ARG:.*]]: !fir.box<!fir.array<?xf32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "dev_x", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK: %[[DEV_X:.*]]:2 = hlfir.declare %[[DEV_X_ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {{.*}}data_attr(#cuf.cuda<device>)
 ! CHECK: %[[HOST_T:.*]]:2 = hlfir.declare %[[HOST_T_ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}}
 ! CHECK: %[[X_COMPONENT:.*]] = hlfir.designate %[[HOST_T]]#0{"x"}
diff --git a/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 b/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90
index eb344d72098df..505da9bbd7386 100644
--- a/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90
+++ b/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90
@@ -50,7 +50,7 @@ subroutine test_assumed_length_alloc(x)
 end subroutine
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_intrinsic(
-! CHECK-SAME:                                                    %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                    %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_intrinsicEx") : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>)
 ! CHECK:           fir.call @_QPtakes_real(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> ()
@@ -58,7 +58,7 @@ subroutine test_assumed_length_alloc(x)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_character_explicit_len(
-! CHECK-SAME:                                                                 %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x"},
+! CHECK-SAME:                                                                 %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>},
 ! CHECK-SAME:                                                                 %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) {
 ! CHECK:           %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_character_explicit_lenEn") : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
@@ -72,7 +72,7 @@ subroutine test_assumed_length_alloc(x)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_character_assumed_len(
-! CHECK-SAME:                                                                %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                                %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_character_assumed_lenEx") : (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>)
 ! CHECK:           fir.call @_QPtakes_char(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> ()
@@ -86,21 +86,21 @@ subroutine test_assumed_length_alloc(x)
 ! CHECK:           fir.call @_QPtakes_real(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> ()
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_simple_allocatable(
-! CHECK-SAME:                                                             %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                             %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_simple_allocatableEx") fortran_attrs<allocatable> : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>)
 ! CHECK:           return
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_simple_pointer(
-! CHECK-SAME:                                                         %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                         %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_simple_pointerEx") fortran_attrs<pointer> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>)
 ! CHECK:           return
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_intentout(
-! CHECK-SAME:                                                    %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                    %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMassumed_rank_testsFtest_intentoutEx") fortran_attrs<allocatable, intent_out> : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>)
 ! CHECK:           %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>
@@ -118,7 +118,7 @@ subroutine test_assumed_length_alloc(x)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func @_QMassumed_rank_testsPtest_assumed_length_alloc(
-! CHECK-SAME:                                                               %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                                                               %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>
 ! CHECK:           %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>) -> index
diff --git a/flang/test/Lower/HLFIR/elemental-array-ops.f90 b/flang/test/Lower/HLFIR/elemental-array-ops.f90
index 35c33ba28932c..a0cd243336152 100644
--- a/flang/test/Lower/HLFIR/elemental-array-ops.f90
+++ b/flang/test/Lower/HLFIR/elemental-array-ops.f90
@@ -155,8 +155,8 @@ end function callee
   l = x==callee(y)
 end subroutine char_return
 ! CHECK-LABEL:   func.func @_QPchar_return(
-! CHECK-SAME:                              %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,3>>> {fir.bindc_name = "x"},
-! CHECK-SAME:                              %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.char<1,3>>> {fir.bindc_name = "y"}) {
+! CHECK-SAME:                              %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,3>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:                              %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.char<1,3>>> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK:           %[[VAL_2:.*]] = fir.alloca !fir.char<1,3> <{bindc_name = ".result"}>
 ! CHECK:           %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>> <{bindc_name = "l", uniq_name = "_QFchar_returnEl"}>
 ! CHECK:           %[[VAL_4:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.logical<4>>>
@@ -208,8 +208,8 @@ subroutine polymorphic_parenthesis(x, y)
   x = (y)
 end subroutine polymorphic_parenthesis
 ! CHECK-LABEL:   func.func @_QPpolymorphic_parenthesis(
-! CHECK-SAME:        %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>> {fir.bindc_name = "x"},
-! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>> {fir.bindc_name = "y"}) {
+! CHECK-SAME:        %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFpolymorphic_parenthesisEx") fortran_attrs<allocatable> : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>)
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFpolymorphic_parenthesisEy") fortran_attrs<intent_in> : (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>)
 ! CHECK:           %[[VAL_4:.*]] = arith.constant 0 : index
@@ -232,8 +232,8 @@ subroutine unlimited_polymorphic_parenthesis(x, y)
   x = (y)
 end subroutine unlimited_polymorphic_parenthesis
 ! CHECK-LABEL:   func.func @_QPunlimited_polymorphic_parenthesis(
-! CHECK-SAME:        %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>> {fir.bindc_name = "x"},
-! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "y"}) {
+! CHECK-SAME:        %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFunlimited_polymorphic_parenthesisEx") fortran_attrs<allocatable> : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>)
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFunlimited_polymorphic_parenthesisEy") fortran_attrs<intent_in> : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>)
 ! CHECK:           %[[VAL_4:.*]] = arith.constant 0 : index
diff --git a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
index c442ba9e95bc6..902e4700fc43e 100644
--- a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
+++ b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
@@ -10,8 +10,8 @@ subroutine test_polymorphic_merge(x, y, r, m)
   r = merge(x, y, m)
 end subroutine test_polymorphic_merge
 ! CHECK-LABEL:   func.func @_QPtest_polymorphic_merge(
-! CHECK-SAME:        %[[VAL_0:.*]]: !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>> {fir.bindc_name = "x"},
-! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>> {fir.bindc_name = "y"},
+! CHECK-SAME:        %[[VAL_0:.*]]: !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_in>},
 ! CHECK-SAME:        %[[VAL_2:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>> {fir.bindc_name = "r"},
 ! CHECK-SAME:        %[[VAL_3:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "m"}) {
 ! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_polymorphic_mergeEm") : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>)
diff --git a/flang/test/Lower/HLFIR/elemental-result-length.f90 b/flang/test/Lower/HLFIR/elemental-result-length.f90
index 4396388fde1f7..dc270e5e9db26 100644
--- a/flang/test/Lower/HLFIR/elemental-result-length.f90
+++ b/flang/test/Lower/HLFIR/elemental-result-length.f90
@@ -16,7 +16,7 @@ subroutine sub2(a,b,c)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QMm1Psub2(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG2:.*]]: !fir.boxchar<1> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 ! CHECK: %[[UNBOX_ARG0:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[UNBOX_ARG0]]#0 typeparams %[[UNBOX_ARG0]]#1 dummy_scope %0 {{.*}} uniq_name("_QMm1Fsub2Ea") fortran_attrs<intent_in> : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
 ! CHECK: %[[UNBOX_ARG1:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
@@ -43,7 +43,7 @@ subroutine sub4(a,b,c)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QMm1Psub4(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG2:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} uniq_name("_QMm1Fsub4Ea") fortran_attrs<intent_in> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>)
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} {{.*}} uniq_name("_QMm1Fsub4Eb") fortran_attrs<intent_in> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>)
 ! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{.*}} {{.*}} uniq_name("_QMm1Fsub4Ec") fortran_attrs<intent_inout> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>)
diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90
index e08a2fca98460..23b3255896ede 100644
--- a/flang/test/Lower/HLFIR/structure-constructor.f90
+++ b/flang/test/Lower/HLFIR/structure-constructor.f90
@@ -314,7 +314,7 @@ subroutine test7(n)
   x = t7(n)
 end subroutine test7
 ! CHECK-LABEL:   func.func @_QPtest7(
-! CHECK-SAME:                        %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n", fir.read_only}) {
+! CHECK-SAME:                        %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest7En") fortran_attrs<intent_in> : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:           %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> <{bindc_name = "x", uniq_name = "_QFtest7Ex"}>
diff --git a/flang/test/Lower/Intrinsics/c_devptr_eq_ne.f90 b/flang/test/Lower/Intrinsics/c_devptr_eq_ne.f90
index c69ff5d5e4f61..b6c4fd29cdae9 100644
--- a/flang/test/Lower/Intrinsics/c_devptr_eq_ne.f90
+++ b/flang/test/Lower/Intrinsics/c_devptr_eq_ne.f90
@@ -10,7 +10,7 @@ function test_c_devptr_eq(d1, d2)
 end
 
 ! CHECK-LABEL: func.func @_QPtest_c_devptr_eq(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d2"}) -> !fir.logical<4> {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d1", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d2", fir.fortran_attrs = #fir.var_attrs<intent_in>}) -> !fir.logical<4> {
 ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_devptr_eqEd1") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>)
 ! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_devptr_eqEd2") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>)
 ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> <{bindc_name = "test_c_devptr_eq", uniq_name = "_QFtest_c_devptr_eqEtest_c_devptr_eq"}>
@@ -38,7 +38,7 @@ function test_c_devptr_ne(d1, d2)
 end
 
 ! CHECK-LABEL: func.func @_QPtest_c_devptr_ne(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d2"}) -> !fir.logical<4> {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d1", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>> {fir.bindc_name = "d2", fir.fortran_attrs = #fir.var_attrs<intent_in>}) -> !fir.logical<4> {
 ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_devptr_neEd1") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>)
 ! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_devptr_neEd2") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>)
 ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> <{bindc_name = "test_c_devptr_ne", uniq_name = "_QFtest_c_devptr_neEtest_c_devptr_ne"}>
diff --git a/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90
index 2e64445904106..ace83c0234166 100644
--- a/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90
+++ b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90
@@ -9,7 +9,7 @@ function test_c_ptr_eq(ptr1, ptr2)
 end
 
 ! CHECK-LABEL: func.func @_QPtest_c_ptr_eq(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2", fir.fortran_attrs = #fir.var_attrs<intent_in>}) -> !fir.logical<4> {
 ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_ptr_eqEptr1") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
 ! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_ptr_eqEptr2") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
 ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> <{bindc_name = "test_c_ptr_eq", uniq_name = "_QFtest_c_ptr_eqEtest_c_ptr_eq"}>
@@ -34,7 +34,7 @@ function test_c_ptr_ne(ptr1, ptr2)
 end
 
 ! CHECK-LABEL: func.func @_QPtest_c_ptr_ne(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2", fir.fortran_attrs = #fir.var_attrs<intent_in>}) -> !fir.logical<4> {
 ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_ptr_neEptr1") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
 ! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFtest_c_ptr_neEptr2") fortran_attrs<intent_in> : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
 ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> <{bindc_name = "test_c_ptr_ne", uniq_name = "_QFtest_c_ptr_neEtest_c_ptr_ne"}>
diff --git a/flang/test/Lower/Intrinsics/dconjg.f90 b/flang/test/Lower/Intrinsics/dconjg.f90
index b223259a39feb..8ab2d0a063764 100644
--- a/flang/test/Lower/Intrinsics/dconjg.f90
+++ b/flang/test/Lower/Intrinsics/dconjg.f90
@@ -5,8 +5,8 @@ subroutine test_dconjg(r, c)
   complex(8), intent(in) :: c
 
 ! CHECK-LABEL: func @_QPtest_dconjg(
-! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "r"},
-! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.read_only}) {
+! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "r", fir.fortran_attrs = #fir.var_attrs<intent_out>},
+! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK:   %[[DS:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:   %[[C_DECL:.*]]:2 = hlfir.declare %[[ARG_1]] dummy_scope %[[DS]] {{.*}}
 ! CHECK:   %[[R_DECL:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %[[DS]] {{.*}}
diff --git a/flang/test/Lower/Intrinsics/dimag.f90 b/flang/test/Lower/Intrinsics/dimag.f90
index 7826d441b2e9c..be3eac4b21bb6 100644
--- a/flang/test/Lower/Intrinsics/dimag.f90
+++ b/flang/test/Lower/Intrinsics/dimag.f90
@@ -5,8 +5,8 @@ subroutine test_dimag(r, c)
   complex(8), intent(in) :: c
 
 ! CHECK-LABEL: func @_QPtest_dimag(
-! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<f64> {fir.bindc_name = "r"},
-! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.read_only}) {
+! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<f64> {fir.bindc_name = "r", fir.fortran_attrs = #fir.var_attrs<intent_out>},
+! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK:   %[[DS:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:   %[[C_DECL:.*]]:2 = hlfir.declare %[[ARG_1]] dummy_scope %[[DS]] {{.*}}
 ! CHECK:   %[[R_DECL:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %[[DS]] {{.*}}
diff --git a/flang/test/Lower/Intrinsics/dreal.f90 b/flang/test/Lower/Intrinsics/dreal.f90
index 3f72aa7d3d630..76f7abd49ed1f 100644
--- a/flang/test/Lower/Intrinsics/dreal.f90
+++ b/flang/test/Lower/Intrinsics/dreal.f90
@@ -5,8 +5,8 @@ subroutine test_dreal(r, c)
   complex(8), intent(in) :: c
 
 ! CHECK-LABEL: func.func @_QPtest_dreal(
-! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<f64> {fir.bindc_name = "r"},
-! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.read_only}) {
+! CHECK-SAME: %[[ARG_0:.*]]: !fir.ref<f64> {fir.bindc_name = "r", fir.fortran_attrs = #fir.var_attrs<intent_out>},
+! CHECK-SAME: %[[ARG_1:.*]]: !fir.ref<complex<f64>> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK:   %[[DS:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:   %[[C:.*]]:2 = hlfir.declare %[[ARG_1]] dummy_scope %[[DS]]
 ! CHECK:   %[[R:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %[[DS]]
diff --git a/flang/test/Lower/Intrinsics/perror.f90 b/flang/test/Lower/Intrinsics/perror.f90
index f67d92640d565..da86d7d6eaf58 100644
--- a/flang/test/Lower/Intrinsics/perror.f90
+++ b/flang/test/Lower/Intrinsics/perror.f90
@@ -35,7 +35,7 @@ subroutine test_perror()
 end subroutine test_perror
 
 ! CHECK-LABEL: func @_QPtest_perror_unknown_length(
-! CHECK-SAME: %[[ARG0:.*]]:  !fir.boxchar<1> {fir.bindc_name = "str"}
+! CHECK-SAME: %[[ARG0:.*]]:  !fir.boxchar<1> {fir.bindc_name = "str", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 subroutine test_perror_unknown_length(str)
     implicit none
     character(len=*), intent(in) :: str
diff --git a/flang/test/Lower/Intrinsics/reduce.f90 b/flang/test/Lower/Intrinsics/reduce.f90
index f5e1125316808..20c705153b192 100644
--- a/flang/test/Lower/Intrinsics/reduce.f90
+++ b/flang/test/Lower/Intrinsics/reduce.f90
@@ -64,7 +64,7 @@ subroutine integer1(a, id, d1, d2)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QMreduce_modPinteger1(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi8>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i8> {fir.bindc_name = "id"}
+! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi8>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.ref<i8> {fir.bindc_name = "id"}
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} uniq_name("_QMreduce_modFinteger1Ea") fortran_attrs<intent_in> : (!fir.box<!fir.array<?xi8>>, !fir.dscope) -> (!fir.box<!fir.array<?xi8>>, !fir.box<!fir.array<?xi8>>)
 ! CHECK: %[[ID:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} uniq_name("_QMreduce_modFinteger1Eid") : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>)
 ! CHECK: %[[ALLOC_RES:.*]] = fir.alloca i8 <{bindc_name = "res", uniq_name = "_QMreduce_modFinteger1Eres"}>
diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90
index 4b970e8cdd608..4aa7203716d6e 100644
--- a/flang/test/Lower/OpenACC/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/acc-declare.f90
@@ -74,8 +74,8 @@ subroutine acc_declare_present_host_and_comp(host, coeffs)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_present_host_and_comp(
-! CHECK-SAME: %[[ARGHOST:.*]]: !fir.ref<!fir.type<_QMacc_declare{{.*}}Tdt_box{{.*}}>> {fir.bindc_name = "host"},
-! CHECK-SAME: %[[ARGCOEFF:.*]]: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "coeffs"})
+! CHECK-SAME: %[[ARGHOST:.*]]: !fir.ref<!fir.type<_QMacc_declare{{.*}}Tdt_box{{.*}}>> {fir.bindc_name = "host", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME: %[[ARGCOEFF:.*]]: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "coeffs", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK-DAG: acc.present{{.*}}name("host")
 ! CHECK-DAG: acc.present{{.*}}name("host%buf")
 ! CHECK-DAG: acc.present{{.*}}name("coeffs")
diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90
index 84ae7e5b1203f..12fe0c9d0b0a4 100644
--- a/flang/test/Lower/OpenMP/array-bounds.f90
+++ b/flang/test/Lower/OpenMP/array-bounds.f90
@@ -39,7 +39,7 @@ module assumed_array_routines
     contains
 
 !HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array(
-!HOST-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
+!HOST-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 !HOST: %[[INTERMEDIATE_ALLOCA:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
 !HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QMassumed_array_routinesFassumed_shape_arrayEarr_read_write") fortran_attrs<intent_inout> : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
 !HOST: %[[C0:.*]] = arith.constant 1 : index
@@ -67,7 +67,7 @@ end subroutine assumed_shape_array
 
 
 !HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array(
-!HOST-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
+!HOST-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 !HOST: %[[ARG0_SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
 !HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]](%[[ARG0_SHAPE]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QMassumed_array_routinesFassumed_size_arrayEarr_read_write") fortran_attrs<intent_inout> : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
 !HOST: %[[ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"}>
diff --git a/flang/test/Lower/OpenMP/flush.f90 b/flang/test/Lower/OpenMP/flush.f90
index baa52ee09d79b..16013c48ca647 100644
--- a/flang/test/Lower/OpenMP/flush.f90
+++ b/flang/test/Lower/OpenMP/flush.f90
@@ -3,7 +3,7 @@
 !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
 
 !CHECK-LABEL:  func.func @_QPflush_standalone
-!CHECK-SAME: %[[ARG_A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG_B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, %[[ARG_C:.*]]: !fir.ref<i32> {fir.bindc_name = "c"})
+!CHECK-SAME: %[[ARG_A:.*]]: !fir.ref<i32> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %[[ARG_B:.*]]: !fir.ref<i32> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %[[ARG_C:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 subroutine flush_standalone(a, b, c)
     integer, intent(inout) :: a, b, c
 
@@ -18,7 +18,7 @@ subroutine flush_standalone(a, b, c)
 end subroutine flush_standalone
 
 !CHECK-LABEL: func.func @_QPflush_parallel
-!CHECK-SAME: %[[ARG_A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG_B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, %[[ARG_C:.*]]: !fir.ref<i32> {fir.bindc_name = "c"})
+!CHECK-SAME: %[[ARG_A:.*]]: !fir.ref<i32> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %[[ARG_B:.*]]: !fir.ref<i32> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %[[ARG_C:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 subroutine flush_parallel(a, b, c)
     integer, intent(inout) :: a, b, c
 !CHECK:    %[[A:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFflush_parallelEa") fortran_attrs<intent_inout> : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
diff --git a/flang/test/Lower/OpenMP/optional-argument-map-2.f90 b/flang/test/Lower/OpenMP/optional-argument-map-2.f90
index 9aac46632c069..d904b0fbefed4 100644
--- a/flang/test/Lower/OpenMP/optional-argument-map-2.f90
+++ b/flang/test/Lower/OpenMP/optional-argument-map-2.f90
@@ -25,7 +25,7 @@ end subroutine routine_boxchar
 end module mod
 
 ! CHECK-LABEL:   func.func @_QMmodProutine_box(
-! CHECK-SAME:      %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "a", fir.optional}) {
+! CHECK-SAME:      %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_inout>, fir.optional}) {
 ! CHECK:           %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>>
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} uniq_name("_QMmodFroutine_boxEa") fortran_attrs<allocatable, intent_inout, optional> : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
@@ -54,7 +54,7 @@ end module mod
 ! CHECK:           }
 
 ! CHECK-LABEL:   func.func @_QMmodProutine_boxchar(
-! CHECK-SAME:      %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a", fir.optional}) {
+! CHECK-SAME:      %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.optional}) {
 ! CHECK:           %[[VAL_0:.*]] = fir.alloca !fir.boxchar<1>
 ! CHECK:           %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
diff --git a/flang/test/Lower/OpenMP/optional-argument-map-3.f90 b/flang/test/Lower/OpenMP/optional-argument-map-3.f90
index e0b762f615d06..f0859b0cd5b84 100644
--- a/flang/test/Lower/OpenMP/optional-argument-map-3.f90
+++ b/flang/test/Lower/OpenMP/optional-argument-map-3.f90
@@ -23,7 +23,7 @@ end subroutine foo
 end module
 
 ! CHECK-LABEL:   func.func @{{.*}}(
-! CHECK-SAME:      %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "dt"},
+! CHECK-SAME:      %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "dt", fir.fortran_attrs = #fir.var_attrs<intent_inout>},
 ! CHECK:           %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
 ! CHECK:           %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope {{.*}}
 ! CHECK:           fir.if %{{.*}} {
diff --git a/flang/test/Lower/OpenMP/optional-argument-map.f90 b/flang/test/Lower/OpenMP/optional-argument-map.f90
index 6458d47526a77..52a44802bfaf0 100644
--- a/flang/test/Lower/OpenMP/optional-argument-map.f90
+++ b/flang/test/Lower/OpenMP/optional-argument-map.f90
@@ -15,8 +15,8 @@ end subroutine test
 end module foo
 
 ! CHECK-LABEL:   func.func @_QMfooPtest(
-! CHECK-SAME:                           %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only},
-! CHECK-SAME:                           %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a", fir.optional}) {
+! CHECK-SAME:                           %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only},
+! CHECK-SAME:                           %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_inout>, fir.optional}) {
 ! CHECK:           %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{.*}} uniq_name("_QMfooFtestEa") fortran_attrs<intent_inout, optional> : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
 ! CHECK:           %{{.*}} = fir.is_present %{{.*}}#1 : (!fir.box<!fir.array<?xf32>>) -> i1
diff --git a/flang/test/Lower/OpenMP/single.f90 b/flang/test/Lower/OpenMP/single.f90
index 1b1a8894f5413..6065fb4f0ab50 100644
--- a/flang/test/Lower/OpenMP/single.f90
+++ b/flang/test/Lower/OpenMP/single.f90
@@ -8,7 +8,7 @@
 !===============================================================================
 
 !CHECK-LABEL: func @_QPomp_single
-!CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"})
+!CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 subroutine omp_single(x)
   integer, intent(inout) :: x
   !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFomp_singleEx") fortran_attrs<intent_inout> : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
@@ -31,7 +31,7 @@ end subroutine omp_single
 !===============================================================================
 
 !CHECK-LABEL: func @_QPomp_single_nowait
-!CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"})
+!CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 subroutine omp_single_nowait(x)
   integer, intent(inout) :: x
   !CHECK:   %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFomp_single_nowaitEx") fortran_attrs<intent_inout> : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
@@ -74,7 +74,7 @@ end subroutine single_allocate
 !===============================================================================
 
 ! CHECK-LABEL: func.func @_QPsingle_privatization(
-! CHECK-SAME:                                     %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x"},
+! CHECK-SAME:                                     %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>},
 ! CHECK-SAME:                                     %[[Y:.*]]: !fir.ref<f64> {fir.bindc_name = "y"}) {
 ! CHECK:           %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFsingle_privatizationEx") : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
 ! CHECK:           %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFsingle_privatizationEy") : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>)
@@ -101,7 +101,7 @@ subroutine single_privatization(x, y)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPsingle_privatization2(
-! CHECK-SAME:                                      %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x"},
+! CHECK-SAME:                                      %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>},
 ! CHECK-SAME:                                      %[[Y:.*]]: !fir.ref<f64> {fir.bindc_name = "y"}) {
 ! CHECK:         %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFsingle_privatization2Ex") : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
 ! CHECK:         %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFsingle_privatization2Ey") : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>)
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90
index dcdc286a138f3..e74a0a9f2deb1 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90
@@ -74,7 +74,7 @@ subroutine reduce(r)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func private @_QFPreduce(
-! CHECK-SAME:                                  %[[VAL_0:.*]]: !fir.box<!fir.array<?xf64>> {fir.bindc_name = "r"}) attributes {{.*}} {
+! CHECK-SAME:                                  %[[VAL_0:.*]]: !fir.box<!fir.array<?xf64>> {fir.bindc_name = "r", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) attributes {{.*}} {
 ! CHECK:           %[[VAL_1:.*]] = fir.address_of(@_QFFreduceEi) : !fir.ref<i32>
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] uniq_name("_QFFreduceEi") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} uniq_name("_QFFreduceEr") fortran_attrs<{{.*}}> : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>)
diff --git a/flang/test/Lower/OpenMP/wsloop-unstructured.f90 b/flang/test/Lower/OpenMP/wsloop-unstructured.f90
index f4a0777a603be..9fbdf48dcf16c 100644
--- a/flang/test/Lower/OpenMP/wsloop-unstructured.f90
+++ b/flang/test/Lower/OpenMP/wsloop-unstructured.f90
@@ -24,10 +24,10 @@ end subroutine sub
 ! that all blocks are terminated
 
 ! CHECK-LABEL:   func.func @_QPsub(
-! CHECK-SAME:                      %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "imax", fir.read_only},
-! CHECK-SAME:                      %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "jmax", fir.read_only},
-! CHECK-SAME:                      %[[VAL_2:.*]]: !fir.ref<!fir.array<?x?xf32>> {fir.bindc_name = "x"},
-! CHECK-SAME:                      %[[VAL_3:.*]]: !fir.ref<!fir.array<?x?xf32>> {fir.bindc_name = "y"}) {
+! CHECK-SAME:                      %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "imax", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only},
+! CHECK-SAME:                      %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "jmax", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only},
+! CHECK-SAME:                      %[[VAL_2:.*]]: !fir.ref<!fir.array<?x?xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:                      %[[VAL_3:.*]]: !fir.ref<!fir.array<?x?xf32>> {fir.bindc_name = "y", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! [...]
 ! CHECK:             omp.wsloop private({{.*}}) {
 ! CHECK-NEXT:          omp.loop_nest (%[[VAL_53:.*]], %[[VAL_54:.*]]) : i32 = ({{.*}}) to ({{.*}}) inclusive step ({{.*}}) {
diff --git a/flang/test/Lower/achar.f90 b/flang/test/Lower/achar.f90
index 3d9be967f7e0b..c916df45e80d4 100644
--- a/flang/test/Lower/achar.f90
+++ b/flang/test/Lower/achar.f90
@@ -12,7 +12,7 @@ subroutine achar_test1(a)
 end subroutine achar_test1
 
 ! CHECK-LABEL: func.func @_QPachar_test1(
-! CHECK-SAME: %[[ARG:.*]]: !fir.ref<i32> {fir.bindc_name = "a", fir.read_only}) {
+! CHECK-SAME: %[[ARG:.*]]: !fir.ref<i32> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK: %[[TMP:.*]] = fir.alloca !fir.char<1>
 ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %[[DSCOPE]] arg 1 uniq_name("_QFachar_test1Ea") fortran_attrs<intent_in>
diff --git a/flang/test/Lower/arguments.f90 b/flang/test/Lower/arguments.f90
index 9667494f0f011..870a8807e5c0f 100644
--- a/flang/test/Lower/arguments.f90
+++ b/flang/test/Lower/arguments.f90
@@ -7,7 +7,7 @@ subroutine sub1(a, b)
 
 ! Check that arguments are correctly set and no local allocation is happening.
 ! CHECK-LABEL: func @_QPsub1(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "a", fir.read_only}, %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "b"})
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "b"})
 ! CHECK-NOT:     fir.alloc
 ! CHECK:         return
 
@@ -31,7 +31,7 @@ integer function fct1(a, b)
 end
 
 ! CHECK-LABEL: func @_QPfct1(
-! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "a", fir.read_only}, %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "b"}) -> i32
+! CHECK-SAME:    %{{.*}}: !fir.ref<i32> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %{{.*}}: !fir.ref<!fir.logical<4>> {fir.bindc_name = "b"}) -> i32
 
 real function fct2(i)
   integer :: i(2, 5)
diff --git a/flang/test/Lower/array-elemental-calls-char-dynamic.f90 b/flang/test/Lower/array-elemental-calls-char-dynamic.f90
index b9a221b29ec64..3eeb3873a1cfb 100644
--- a/flang/test/Lower/array-elemental-calls-char-dynamic.f90
+++ b/flang/test/Lower/array-elemental-calls-char-dynamic.f90
@@ -186,8 +186,8 @@ elemental function f_poly(p1, p2)
 end subroutine
 ! CHECK-LABEL:   func.func @_QPtest_polymorphic(
 ! CHECK-SAME:      %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "res"},
-! CHECK-SAME:      %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p1"},
-! CHECK-SAME:      %[[ARG2:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p2"}) {
+! CHECK-SAME:      %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p1", fir.fortran_attrs = #fir.var_attrs<intent_in>},
+! CHECK-SAME:      %[[ARG2:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p2", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK:           %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} uniq_name("_QFtest_polymorphicEp1") fortran_attrs<intent_in> : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>)
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} uniq_name("_QFtest_polymorphicEp2") fortran_attrs<intent_in> : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>)
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index 06d6af28ee55e..29a1a162ea718 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -104,14 +104,14 @@ subroutine test_actual_arg_intent_in(x)
 ! at the inner call site, so the inner procedure still generates copy-back.
 ! The outer array must therefore not be marked fir.read_only.
 ! CHECK-LABEL: func.func @_QPtest_forwarded_intent_in(
-! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<4xf32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<4xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 subroutine test_forwarded_intent_in(x)
   real, intent(in) :: x(4)
   call test_forwarded_without_intent(x)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtest_forwarded_without_intent(
-! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<4xf32>> {fir.bindc_name = "x"}) {
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<4xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 subroutine test_forwarded_without_intent(x)
   real :: x(4)
 ! CHECK: hlfir.copy_in
@@ -142,7 +142,7 @@ subroutine test_actual_arg_intent_in_ptr_component(x)
 ! the target's contents, so the callee may define the target and copy-out is
 ! required.
 ! CHECK-LABEL: func.func @_QPtest_actual_intent_in_pointer(
-! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "pi", fir.read_only}) {
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "pi", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 subroutine test_actual_intent_in_pointer(pi)
   integer, intent(in), pointer :: pi(:)
 ! CHECK: hlfir.copy_in
diff --git a/flang/test/Lower/default-initialization.f90 b/flang/test/Lower/default-initialization.f90
index 9b0fcf115ccd3..093310a80b528 100644
--- a/flang/test/Lower/default-initialization.f90
+++ b/flang/test/Lower/default-initialization.f90
@@ -78,7 +78,7 @@ subroutine intent_out(x)
   ! Test that optional intent(out) are default initialized only when
   ! present.
   ! CHECK-LABEL: func @_QMtest_dinitPintent_out_optional(
-  ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>> {fir.bindc_name = "x", fir.optional})
+  ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>, fir.optional})
   subroutine intent_out_optional(x)
     ! CHECK: %[[x:.*]]:2 = hlfir.declare %[[arg0]] {{.*}} uniq_name("_QMtest_dinitFintent_out_optionalEx") fortran_attrs<intent_out, optional>
     ! CHECK: %[[isPresent:.*]] = fir.is_present %[[x]]#0 : (!fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>) -> i1
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 8fbed8fbbf1f1..984ce663a5fca 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -116,7 +116,7 @@ subroutine test_end_finalization2(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_end_finalization2(
-! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "a"}) {
+! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 ! CHECK:   %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
 ! CHECK:   %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> <{bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_end_finalization2Et"}>
 ! CHECK:   %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
@@ -152,7 +152,7 @@ subroutine test_finalize_intent_out(t)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_finalize_intent_out(
-! CHECK-SAME: %[[T:.*]]: !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {fir.bindc_name = "t"}) {
+! CHECK-SAME: %[[T:.*]]: !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {fir.bindc_name = "t", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
 ! CHECK: fir.call @_FortranADestroy(%{{.*}})
 ! CHECK: return
diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90
index 72505edc87d57..d5a98b6801922 100644
--- a/flang/test/Lower/dispatch.f90
+++ b/flang/test/Lower/dispatch.f90
@@ -107,7 +107,7 @@ subroutine p1_proc4_arg1(i, this)
       integer, intent(in) :: i
       class(p1) :: this
     end subroutine
-    ! CHECK-LABEL: func.func @_QMcall_dispatchPp1_proc4_arg1(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}, %{{.*}}: !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
+    ! CHECK-LABEL: func.func @_QMcall_dispatchPp1_proc4_arg1(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %{{.*}}: !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
 
     subroutine tbp_nopass()
     end subroutine
@@ -127,7 +127,7 @@ subroutine tbp_pass_arg1(i, this)
       integer, intent(in) :: i
       class(p1) :: this
     end subroutine
-    ! CHECK-LABEL: func.func @_QMcall_dispatchPtbp_pass_arg1(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}, %{{.*}}: !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
+    ! CHECK-LABEL: func.func @_QMcall_dispatchPtbp_pass_arg1(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %{{.*}}: !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
 
     subroutine check_dispatch(p)
       class(p1) :: p
diff --git a/flang/test/Lower/intentout-deallocate.f90 b/flang/test/Lower/intentout-deallocate.f90
index 8cfb213a5a0c5..9c82b15211e7f 100644
--- a/flang/test/Lower/intentout-deallocate.f90
+++ b/flang/test/Lower/intentout-deallocate.f90
@@ -48,7 +48,7 @@ subroutine sub1(a)
 ! Check inline deallocation of allocatable intent(out) on the callee side.
 
 ! CHECK-LABEL: func.func @_QMmod1Psub1(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>})
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub1Ea"
 ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
@@ -114,7 +114,7 @@ subroutine sub5(t)
 ! is done with a runtime call.
 
 ! CHECK-LABEL: func.func @_QMmod1Psub5(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>> {fir.bindc_name = "t"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>> {fir.bindc_name = "t", fir.fortran_attrs = #fir.var_attrs<intent_out>})
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub5Et"
 ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>>) -> !fir.heap<!fir.type<_QMmod1Tt1{{[<]?}}{i:i32}{{[>]?}}>>
@@ -160,7 +160,7 @@ subroutine sub9(a)
 ! Check inline deallocation of optional allocatable intent(out) on the callee side.
 
 ! CHECK-LABEL: func.func @_QMmod1Psub9(
-! CHECK-SAME:  %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.optional})
+! CHECK-SAME:  %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>, fir.optional})
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub9Ea"
 ! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0]]{{[#0]*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> i1
 ! CHECK: fir.if %[[IS_PRESENT]] {
@@ -188,7 +188,7 @@ subroutine sub10(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMmod1Psub10(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub10Ea"
 ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
@@ -215,7 +215,7 @@ subroutine sub12(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMmod1Psub12(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea"
 ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
@@ -234,7 +234,7 @@ subroutine sub12(a)
 ! CHECK: }
 
 ! CHECK-LABEL: func.func @_QMmod1Psub13(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea"
 ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
@@ -258,7 +258,7 @@ subroutine sub14(p)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMmod1Psub14(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>> {fir.bindc_name = "p"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub14Ep"
 ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>) -> !fir.heap<!fir.type<_QMmod1Tt{a:i32}>>
@@ -277,7 +277,7 @@ subroutine sub15(p)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMmod1Psub15(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<none>>> {fir.bindc_name = "p"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<none>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub15Ep"
 ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref<!fir.class<!fir.heap<none>>>
 ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.class<!fir.heap<none>>) -> !fir.heap<none>
@@ -295,7 +295,7 @@ subroutine sub16(p)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMmod1Psub16(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>> {fir.bindc_name = "p", fir.optional}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_out>, fir.optional}) {
 ! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub16Ep"
 ! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0]]{{[#0]*}} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMmod1Tt{a:i32}>>>>) -> i1
 ! CHECK: fir.if %[[IS_PRESENT]] {
diff --git a/flang/test/Lower/parent-component.f90 b/flang/test/Lower/parent-component.f90
index c8b464880e5f2..8c5c0593230ad 100644
--- a/flang/test/Lower/parent-component.f90
+++ b/flang/test/Lower/parent-component.f90
@@ -29,13 +29,13 @@ subroutine print_scalar(a)
     type(p), intent(in) :: a
     print*, a
   end subroutine
-  ! CHECK-LABEL: func.func private @_QFPprint_scalar(%{{.*}}: !fir.ref<!fir.type<_QFTp{a:i32}>> {fir.bindc_name = "a"})
+  ! CHECK-LABEL: func.func private @_QFPprint_scalar(%{{.*}}: !fir.ref<!fir.type<_QFTp{a:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 
   subroutine print_p(a)
     type(p), intent(in) :: a(2)
     print*, a
   end subroutine
-  ! CHECK-LABEL: func.func private @_QFPprint_p(%{{.*}}: !fir.ref<!fir.array<2x!fir.type<_QFTp{a:i32}>>> {fir.bindc_name = "a"})
+  ! CHECK-LABEL: func.func private @_QFPprint_p(%{{.*}}: !fir.ref<!fir.array<2x!fir.type<_QFTp{a:i32}>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 
   subroutine init_with_slice()
     type(c) :: y(2) = [ c(11, 21), c(12, 22) ]
diff --git a/flang/test/Lower/polymorphic-temp.f90 b/flang/test/Lower/polymorphic-temp.f90
index 956dfaf1b4dcc..4f7c4ffb53801 100644
--- a/flang/test/Lower/polymorphic-temp.f90
+++ b/flang/test/Lower/polymorphic-temp.f90
@@ -63,7 +63,7 @@ subroutine test_temp_from_intrinsic_reshape(i)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_reshape(
-! CHECK-SAME: %[[I:.*]]: !fir.class<!fir.array<20x20xnone>> {fir.bindc_name = "i"}) {
+! CHECK-SAME: %[[I:.*]]: !fir.class<!fir.array<20x20xnone>> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[A:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x?xnone>>> <{bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_temp_from_intrinsic_reshapeEa"}>
 ! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]]
@@ -85,7 +85,7 @@ subroutine test_temp_from_intrinsic_pack(i, mask)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_pack(
-! CHECK-SAME: %[[I:.*]]: !fir.class<!fir.array<20x20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "i"}, %[[MASK:.*]]: !fir.ref<!fir.array<20x20x!fir.logical<4>>> {fir.bindc_name = "mask"}) {
+! CHECK-SAME: %[[I:.*]]: !fir.class<!fir.array<20x20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[MASK:.*]]: !fir.ref<!fir.array<20x20x!fir.logical<4>>> {fir.bindc_name = "mask", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[TMP_RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>>>
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]]
 ! CHECK: %[[MASK_DECL:.*]]:2 = hlfir.declare %[[MASK]]
@@ -109,7 +109,7 @@ subroutine test_temp_from_unpack(v, m, f)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_unpack(
-! CHECK-SAME: %[[V:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "v"}, %[[M:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>> {fir.bindc_name = "m"}, %[[F:.*]]: !fir.class<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "f"}) {
+! CHECK-SAME: %[[V:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "v", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[M:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>> {fir.bindc_name = "m", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[F:.*]]: !fir.class<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "f", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[TMP_RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>>>
 ! CHECK: %[[F_DECL:.*]]:2 = hlfir.declare %[[F]]
 ! CHECK: %[[M_DECL:.*]]:2 = hlfir.declare %[[M]]
@@ -132,7 +132,7 @@ subroutine test_temp_from_intrinsic_cshift(a, shift)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_cshift(
-! CHECK-SAME: %[[ARRAY:.*]]: !fir.class<!fir.array<20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "a"}, %[[SHIFT:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}) {
+! CHECK-SAME: %[[ARRAY:.*]]: !fir.class<!fir.array<20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[SHIFT:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}) {
 ! CHECK: %[[ARRAY_DECL:.*]]:2 = hlfir.declare %[[ARRAY]]
 ! CHECK: %[[SHIFT_DECL:.*]]:2 = hlfir.declare %[[SHIFT]]
 ! CHECK: %[[CSHIFT:.*]] = hlfir.cshift %[[ARRAY_DECL]]#0 %[[SHIFT_DECL]]#0 : (!fir.class<!fir.array<20x!fir.type<_QMpoly_tmpTp1{a:i32}>>>, !fir.ref<i32>) -> !hlfir.expr<20x!fir.type<_QMpoly_tmpTp1{a:i32}>?>
@@ -146,7 +146,7 @@ subroutine test_temp_from_intrinsic_eoshift(a, shift, b)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_eoshift(
-! CHECK-SAME: %[[ARRAY:.*]]: !fir.class<!fir.array<20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "a"}, %[[SHIFT:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}, %[[BOUNDARY:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "b"}) {
+! CHECK-SAME: %[[ARRAY:.*]]: !fir.class<!fir.array<20x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[SHIFT:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}, %[[BOUNDARY:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[ARRAY_DECL:.*]]:2 = hlfir.declare %[[ARRAY]]
 ! CHECK: %[[BOUNDARY_DECL:.*]]:2 = hlfir.declare %[[BOUNDARY]]
 ! CHECK: %[[SHIFT_DECL:.*]]:2 = hlfir.declare %[[SHIFT]]
@@ -159,7 +159,7 @@ subroutine test_temp_from_intrinsic_transfer(source, mold)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_transfer(
-! CHECK-SAME: %[[SOURCE:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "source"}, %[[MOLD:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "mold"}) {
+! CHECK-SAME: %[[SOURCE:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "source", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[MOLD:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "mold", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[TMP_RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpoly_tmpTp1{a:i32}>>>>
 ! CHECK: %[[MOLD_DECL:.*]]:2 = hlfir.declare %[[MOLD]]
 ! CHECK: %[[SOURCE_DECL:.*]]:2 = hlfir.declare %[[SOURCE]]
@@ -174,7 +174,7 @@ subroutine test_temp_from_intrinsic_transpose(matrix)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_transpose(
-! CHECK-SAME: %[[MATRIX:.*]]: !fir.class<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "matrix"}) {
+! CHECK-SAME: %[[MATRIX:.*]]: !fir.class<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>> {fir.bindc_name = "matrix", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[MATRIX_DECL:.*]]:2 = hlfir.declare %[[MATRIX]]
 ! CHECK: %[[TRANS:.*]] = hlfir.transpose %[[MATRIX_DECL]]#0 : (!fir.class<!fir.array<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>>>) -> !hlfir.expr<?x?x!fir.type<_QMpoly_tmpTp1{a:i32}>?>
 
@@ -189,7 +189,7 @@ subroutine test_merge_intrinsic(a, b)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "b"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[ARG1]]
 ! CHECK: %[[DES_A:.*]] = hlfir.designate %[[A_DECL]]#0{"a"}   : (!fir.class<!fir.type<_QMpoly_tmpTp1{a:i32}>>) -> !fir.ref<i32>
@@ -208,7 +208,7 @@ subroutine test_merge_intrinsic2(a, b, i)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic2(
-! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>> {fir.bindc_name = "a", fir.read_only}, %[[B:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>> {fir.bindc_name = "b"}, %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}) {
+! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %[[B:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
 ! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]]
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]]
@@ -230,7 +230,7 @@ subroutine test_merge_intrinsic3(a, b, i)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic3(
-! CHECK-SAME: %[[A:.*]]: !fir.class<none> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.class<none> {fir.bindc_name = "b"}, %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}) {
+! CHECK-SAME: %[[A:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[B:.*]]: !fir.class<none> {fir.bindc_name = "b", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
 ! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]]
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]]
@@ -247,7 +247,7 @@ subroutine test_merge_intrinsic4(i)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic4(
-! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}) {
+! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.heap<none>> <{bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic4Ea"}>
 ! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.heap<none>
 ! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
@@ -274,7 +274,7 @@ subroutine test_merge_intrinsic5(i)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic5(
-! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}) {
+! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.ptr<none>> <{bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic5Ea"}>
 ! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.ptr<none>
 ! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.ptr<none>) -> !fir.class<!fir.ptr<none>>
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index 2cf2d517edcfa..822aaa820cdd3 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -66,7 +66,7 @@ elemental subroutine assign_p1_int(lhs, rhs)
     lhs%b = rhs
   End Subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPassign_p1_int(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "lhs"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "rhs", fir.read_only}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "lhs", fir.fortran_attrs = #fir.var_attrs<intent_inout>}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "rhs", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}
 ! CHECK-SAME:    attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>}
 ! CHECK:         %[[LHS:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFassign_p1_intElhs") fortran_attrs<intent_inout>
 ! CHECK:         %[[RHS:.*]]:2 = hlfir.declare %[[ARG1]]{{.*}}uniq_name("_QMpolymorphic_testFassign_p1_intErhs") fortran_attrs<intent_in>
@@ -80,7 +80,7 @@ elemental integer function elemental_fct(this)
     elemental_fct = this%a
   end function
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPelemental_fct(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK-SAME:    -> i32 attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>}
 ! CHECK:         %[[THIS:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFelemental_fctEthis") fortran_attrs<intent_in>
 ! CHECK:         %[[A:.*]] = hlfir.designate %[[THIS]]#0{"a"}
@@ -90,7 +90,7 @@ elemental subroutine elemental_sub(this)
     this%a = this%a * this%b
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPelemental_sub(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 ! CHECK-SAME:    attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>}
 ! CHECK:         %[[THIS:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK:         hlfir.designate %[[THIS]]#0{"a"}
@@ -102,7 +102,7 @@ elemental subroutine elemental_sub_pass(c, this)
     this%a = this%a * this%b + c
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPelemental_sub_pass(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.read_only}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "this", fir.fortran_attrs = #fir.var_attrs<intent_inout>})
 ! CHECK-SAME:    attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>}
 
   logical elemental function lt(i, poly)
@@ -111,7 +111,7 @@ logical elemental function lt(i, poly)
     lt = i < poly%a
   End Function
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPlt(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.read_only}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "poly"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %[[ARG1:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "poly", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK-SAME:    -> !fir.logical<4> attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>}
 ! CHECK:         %[[I:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFltEi") fortran_attrs<intent_in>
 ! CHECK:         %[[POLY:.*]]:2 = hlfir.declare %[[ARG1]]{{.*}}uniq_name("_QMpolymorphic_testFltEpoly") fortran_attrs<intent_in>
@@ -123,7 +123,7 @@ subroutine component_access(p)
     print*, p%a
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPcomponent_access(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFcomponent_accessEp")
 ! CHECK:         %[[A:.*]] = hlfir.designate %[[P]]#0{"a"}   : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.ref<i32>
 ! CHECK:         %[[A_LD:.*]] = fir.load %[[A]] : !fir.ref<i32>
@@ -198,7 +198,7 @@ subroutine polymorphic_to_nonpolymorphic(p)
     t = p
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPpolymorphic_to_nonpolymorphic
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK:         hlfir.assign
 
@@ -212,7 +212,7 @@ subroutine nonpolymorphic_to_polymorphic(p, t)
     p(0:1) => t
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPnonpolymorphic_to_polymorphic(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>>>> {fir.bindc_name = "p"}, %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>> {fir.bindc_name = "t", fir.target}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}, %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>> {fir.bindc_name = "t", fir.target}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFnonpolymorphic_to_polymorphicEp") fortran_attrs<pointer>
 ! CHECK:         %[[T:.*]]:2 = hlfir.declare %[[ARG1]]{{.*}}uniq_name("_QMpolymorphic_testFnonpolymorphic_to_polymorphicEt") fortran_attrs<target>
 ! CHECK:         %[[REBOX:.*]] = fir.rebox %[[T]]#0 : (!fir.class<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testFnonpolymorphic_to_polymorphicTp1>>>>
@@ -288,7 +288,7 @@ subroutine call_sub_with_type_array(p)
     call sub_with_type_array(p)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPcall_sub_with_type_array(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"})
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK:         %[[P_LD:.*]] = fir.load %[[P]]#0
 ! CHECK:         %[[REBOX:.*]] = fir.rebox %[[P_LD]]
@@ -310,7 +310,7 @@ subroutine takes_p1(p)
     class(p1), intent(in) :: p
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtakes_p1(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
 ! TODO: implement polymorphic temporary in lowering
 !  subroutine no_reassoc_poly_value(a, i)
@@ -363,7 +363,7 @@ subroutine up_input(a)
     class(*), intent(in) :: a
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPup_input(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
   subroutine pass_trivial_to_up()
     call up_input('hello')
@@ -389,7 +389,7 @@ subroutine up_arr_input(a)
     class(*), intent(in) :: a(2)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPup_arr_input(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<2xnone>> {fir.bindc_name = "a"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<2xnone>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
   subroutine pass_trivial_arr_to_up()
     character :: c(2)
@@ -495,7 +495,7 @@ subroutine test_elemental_poly_array(p)
     print *, p%elemental_fct()
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_poly_array(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<5x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<5x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK:         hlfir.elemental
 
@@ -504,7 +504,7 @@ subroutine test_elemental_poly_array_2d(p)
     print *, p%elemental_fct()
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_poly_array_2d(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<5x5x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<5x5x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]
 
   subroutine test_elemental_sub_array()
@@ -521,7 +521,7 @@ subroutine test_elemental_sub_poly_array(p)
     call p%elemental_sub_pass(3)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_sub_poly_array(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<10x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<10x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
   subroutine test_elemental_sub_array_assumed(t)
     type(p1) :: t(:)
@@ -537,7 +537,7 @@ subroutine test_elemental_sub_poly_array_assumed(p)
     call p%elemental_sub_pass(5)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_sub_poly_array_assumed(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
 
   subroutine write_p1(dtv, unit, iotype, v_list, iostat, iomsg)
@@ -550,7 +550,7 @@ subroutine write_p1(dtv, unit, iotype, v_list, iostat, iomsg)
     ! dummy subroutine for testing purpose
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPwrite_p1(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "dtv"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "dtv", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
   subroutine read_p1(dtv, unit, iotype, v_list, iostat, iomsg)
     class(p1), intent(inout) :: dtv
@@ -562,7 +562,7 @@ subroutine read_p1(dtv, unit, iotype, v_list, iostat, iomsg)
     ! dummy subroutine for testing purpose
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPread_p1(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "dtv"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "dtv", fir.fortran_attrs = #fir.var_attrs<intent_inout>}
 
   subroutine test_polymorphic_io()
     type(p1), target :: t
@@ -600,13 +600,13 @@ subroutine test_unlimited_polymorphic_intentout(a)
     class(*), intent(out) :: a
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_unlimited_polymorphic_intentout(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}
 
   subroutine test_polymorphic_intentout(a)
     class(p1), intent(out) :: a
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_polymorphic_intentout(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}
 
   subroutine rebox_up_to_record_type(p)
     class(*), allocatable, target :: p(:,:)
@@ -671,7 +671,7 @@ subroutine test_poly_array_component_output(p)
     print*, p(:)%a
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_poly_array_component_output(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]
 
 
@@ -680,13 +680,13 @@ subroutine opt_int(i)
     call opt_up(i)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPopt_int(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.optional, fir.read_only}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "i", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.optional, fir.read_only}
 
   subroutine opt_up(up)
     class(*), optional, intent(in) :: up
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPopt_up(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "up", fir.optional}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "up", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.optional}
 
   function rhs()
     class(p1), pointer :: rhs
@@ -714,7 +714,7 @@ subroutine up_pointer(p)
     class(*), pointer, intent(in) :: p
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPup_pointer(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<none>>> {fir.bindc_name = "p", fir.read_only}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<none>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}
 
   subroutine test_char_to_up_pointer(c)
     character(*), target :: c
@@ -794,7 +794,7 @@ subroutine test_parent_comp_opt(p)
     call takes_p1_opt(p%p1)
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_parent_comp_opt(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{p1:!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>,c:f32}>>>> {fir.bindc_name = "p"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{p1:!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>,c:f32}>>>> {fir.bindc_name = "p", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 ! CHECK:         %[[P:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMpolymorphic_testFtest_parent_comp_optEp") fortran_attrs<allocatable>
 ! CHECK:         %{{.*}} = fir.call @_FortranAAllocatableAllocate(
 ! CHECK:         %[[P_LD:.*]] = fir.load %[[P]]#0
@@ -865,7 +865,7 @@ subroutine pass_up(up)
     class(*), intent(in) :: up
   end subroutine
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPpass_up(
-! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "up"}
+! CHECK-SAME:    %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "up", fir.fortran_attrs = #fir.var_attrs<intent_in>}
 
 ! TODO: unlimited polymorphic temporary in lowering
 !  subroutine parenthesized_up(a)
diff --git a/flang/test/Lower/repack-arrays-finalized-dummy.f90 b/flang/test/Lower/repack-arrays-finalized-dummy.f90
index 0c0a914d08056..a9e132cad31f9 100644
--- a/flang/test/Lower/repack-arrays-finalized-dummy.f90
+++ b/flang/test/Lower/repack-arrays-finalized-dummy.f90
@@ -17,7 +17,7 @@ end subroutine my_final
   end interface
 contains
 ! CHECK-LABEL:   func.func @_QMmPtest(
-! CHECK-SAME:                         %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.class<!fir.array<?x!fir.type<_QMmTt>>> {fir.bindc_name = "x"}) {
+! CHECK-SAME:                         %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.class<!fir.array<?x!fir.type<_QMmTt>>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
   subroutine test(x)
     class(t), intent(out) :: x(:)
 ! CHECK:           %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]] heap whole : (!fir.class<!fir.array<?x!fir.type<_QMmTt>>>) -> !fir.class<!fir.array<?x!fir.type<_QMmTt>>>
diff --git a/flang/test/Lower/repack-arrays.f90 b/flang/test/Lower/repack-arrays.f90
index 339b4a723abc8..d7a7fbadf1292 100644
--- a/flang/test/Lower/repack-arrays.f90
+++ b/flang/test/Lower/repack-arrays.f90
@@ -64,7 +64,7 @@ subroutine test3(x)
 end subroutine test3
 
 ! ALL-LABEL:   func.func @_QPtest4(
-! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) {
 subroutine test4(x)
   real, intent(inout) :: x(:)
 ! ALL:           %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
@@ -82,7 +82,7 @@ subroutine test4(x)
 end subroutine test4
 
 ! ALL-LABEL:   func.func @_QPtest5(
-! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 subroutine test5(x)
   real, intent(in) :: x(:)
 ! ALL:           %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
@@ -99,7 +99,7 @@ subroutine test5(x)
 end subroutine test5
 
 ! ALL-LABEL:   func.func @_QPtest6(
-! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+! ALL-SAME:                        %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 subroutine test6(x)
   real, intent(out) :: x(:)
 ! ALL:           %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
diff --git a/flang/test/Lower/select-type-2.f90 b/flang/test/Lower/select-type-2.f90
index 57c4661d0115e..d32e9aa8cf44b 100644
--- a/flang/test/Lower/select-type-2.f90
+++ b/flang/test/Lower/select-type-2.f90
@@ -29,7 +29,7 @@ subroutine select_type1(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_2Pselect_type1(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_2Tp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_2Tp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CHECK:      %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope {{.*}} uniq_name("_QMselect_type_2Fselect_type1Ea") fortran_attrs<intent_in>
 ! CHECK:      %[[TDESC_P3_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_2Tp3
 ! CHECK:      %[[TDESC_P3_CONV:.*]] = fir.convert %[[TDESC_P3_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90
index 4fa31d9180eac..58a0d4fae6db2 100644
--- a/flang/test/Lower/select-type.f90
+++ b/flang/test/Lower/select-type.f90
@@ -55,7 +55,7 @@ subroutine select_type1(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type1(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CHECK: fir.select_type %[[A]]#1 : !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
 ! CHECK-SAME: [#fir.type_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^[[TYPE_IS_BLK:.*]], #fir.class_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^[[CLASS_IS_P1_BLK:.*]], #fir.class_is<!fir.type<_QMselect_type_lower_testTp2{{.*}}>>, ^[[CLASS_IS_P2_BLK:.*]], unit, ^[[DEFAULT_BLOCK:.*]]]
@@ -68,7 +68,7 @@ subroutine select_type1(a)
 ! CHECK: ^[[DEFAULT_BLOCK]]
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type1(
-! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
+! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CFG: %[[A:.*]]:2 = hlfir.declare %[[ARG0]]
 ! CFG: %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
 ! CFG: %[[BOX_TDESC:.*]] = fir.box_tdesc %[[A]]#1 : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
@@ -166,7 +166,7 @@ subroutine select_type3(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type3(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "a", fir.read_only})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only})
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]]{{.*}}uniq_name("_QMselect_type_lower_testFselect_type3Ea") fortran_attrs<intent_in, pointer>
 ! CHECK: %[[ARG0_LOAD:.*]] = fir.load %[[A]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[SELECTOR:.*]] = hlfir.designate %[[ARG0_LOAD]] (%{{.*}})  : (!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>, index) -> !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
@@ -177,7 +177,7 @@ subroutine select_type3(a)
 ! CHECK: ^[[DEFAULT_BLK]]
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type3(
-! CFG-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "a", fir.read_only}) {
+! CFG-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) {
 ! CFG:      %[[SELECTOR:.*]] = hlfir.designate %{{.*}} (%{{.*}})  : (!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>, index) -> !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
 ! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
 ! CFG:      %[[SELECTOR_TDESC:.*]] = fir.box_tdesc %[[SELECTOR]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<{{.*}}>
@@ -215,7 +215,7 @@ subroutine select_type4(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type4(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope {{.*}} uniq_name("_QMselect_type_lower_testFselect_type4Ea") fortran_attrs<intent_in>
 ! CHECK: fir.select_type %[[A]]#1 : !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
 ! CHECK-SAME: [#fir.type_is<!fir.type<_QMselect_type_lower_testTp3K8{{.*}}>>, ^[[P3_8:.*]], #fir.type_is<!fir.type<_QMselect_type_lower_testTp3K4{{.*}}>>, ^[[P3_4:.*]], #fir.class_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^[[P1:.*]], unit, ^[[EXIT:.*]]]
@@ -225,7 +225,7 @@ subroutine select_type4(a)
 ! CHECK: ^[[EXIT]]
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type4(
-! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
+! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CFG:      %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope {{.*}} uniq_name("_QMselect_type_lower_testFselect_type4Ea") fortran_attrs<intent_in>
 ! CFG:      %[[TDESC_P3_8_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp3K8
 ! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[A]]#1 : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<{{.*}}>
@@ -278,7 +278,7 @@ subroutine select_type5(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type5(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>})
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg 1 uniq_name("_QMselect_type_lower_testFselect_type5Ea") fortran_attrs<intent_in> : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>)
 ! CHECK: fir.select_type %[[A]]#1 : !fir.class<none>
 ! CHECK-SAME: [#fir.type_is<i8>, ^[[I8_BLK:.*]], #fir.type_is<i32>, ^[[I32_BLK:.*]], #fir.type_is<f32>, ^[[F32_BLK:.*]], #fir.type_is<!fir.logical<4>>, ^[[LOG_BLK:.*]], #fir.type_is<!fir.char<1,?>>, ^[[CHAR_BLK:.*]], unit, ^[[DEFAULT:.*]]]
@@ -290,7 +290,7 @@ subroutine select_type5(a)
 ! CHECK: ^[[DEFAULT]]
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type5(
-! CFG-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}) {
+! CFG-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_in>}) {
 ! CFG: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg 1 uniq_name("_QMselect_type_lower_testFselect_type5Ea") fortran_attrs<intent_in> : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>)
 ! CFG: %[[INT8_TC:.*]] = arith.constant 7 : i8
 ! CFG: %[[TYPE_CODE:.*]] = fir.box_typecode %[[A]]#1 : (!fir.class<none>) -> i8
@@ -411,7 +411,7 @@ subroutine select_type7(a)
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type7(
-! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"})
+! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>})
 ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[DSCOPE]] arg 1 {{.*}}uniq_name("_QMselect_type_lower_testFselect_type7Ea"){{.*}} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>)
 ! CHECK: fir.select_type %[[DECL]]#1 :
@@ -421,7 +421,7 @@ subroutine select_type7(a)
 !   class is (p4) -> class is (p2) -> class is (p1) -> class default
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type7(
-! CFG-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}) {
+! CFG-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a", fir.fortran_attrs = #fir.var_attrs<intent_out>}) {
 ! CFG:      %[[TDESC_P4_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp4
 ! CFG:      %[[TDESC_P4_CONV:.*]] = fir.convert %[[TDESC_P4_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %{{.*}} : (!fir.class<none>) -> !fir.box<none>
diff --git a/flang/test/Lower/unsigned-ops.f90 b/flang/test/Lower/unsigned-ops.f90
index c6b0521c1e294..820cca63ec330 100644
--- a/flang/test/Lower/unsigned-ops.f90
+++ b/flang/test/Lower/unsigned-ops.f90
@@ -5,7 +5,7 @@ unsigned function f01(u, v)
   f01 = u + v - 1u
 end
 
-!CHECK: func.func @_QPf01(%[[ARG0:.*]]: !fir.ref<ui32> {fir.bindc_name = "u", fir.read_only}, %[[ARG1:.*]]: !fir.ref<ui32> {fir.bindc_name = "v", fir.read_only}) -> ui32 {
+!CHECK: func.func @_QPf01(%[[ARG0:.*]]: !fir.ref<ui32> {fir.bindc_name = "u", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %[[ARG1:.*]]: !fir.ref<ui32> {fir.bindc_name = "v", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) -> ui32 {
 !CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
 !CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
 !CHECK: %[[VAL_1:.*]] = fir.alloca ui32 <{bindc_name = "f01", uniq_name = "_QFf01Ef01"}>
@@ -30,7 +30,7 @@ unsigned function f02(u, v)
   f02 = u ** v - 1u
 end
 
-!CHECK: func.func @_QPf02(%[[ARG0:.*]]: !fir.ref<ui32> {fir.bindc_name = "u", fir.read_only}, %[[ARG1:.*]]: !fir.ref<ui32> {fir.bindc_name = "v", fir.read_only}) -> ui32 {
+!CHECK: func.func @_QPf02(%[[ARG0:.*]]: !fir.ref<ui32> {fir.bindc_name = "u", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}, %[[ARG1:.*]]: !fir.ref<ui32> {fir.bindc_name = "v", fir.fortran_attrs = #fir.var_attrs<intent_in>, fir.read_only}) -> ui32 {
 !CHECK: %[[C1_i32:.*]] = arith.constant 1 : i32
 !CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
 !CHECK: %[[VAL_1:.*]] = fir.alloca ui32 <{bindc_name = "f02", uniq_name = "_QFf02Ef02"}>
diff --git a/flang/test/Lower/volatile-string.f90 b/flang/test/Lower/volatile-string.f90
index 11fdf95f00368..65db6c89b1979 100644
--- a/flang/test/Lower/volatile-string.f90
+++ b/flang/test/Lower/volatile-string.f90
@@ -69,7 +69,7 @@ subroutine assign_different_length(string)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func private @_QFPassign_same_length(
-! CHECK-SAME:                                              %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
+! CHECK-SAME:                                              %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "x", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
 ! CHECK:           %[[VAL_1:.*]] = arith.constant 3 : index
 ! CHECK:           %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
 ! CHECK:           %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
@@ -83,7 +83,7 @@ subroutine assign_different_length(string)
 ! CHECK:         }
 
 ! CHECK-LABEL:   func.func private @_QFPassign_different_length(
-! CHECK-SAME:                                                   %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "string"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
+! CHECK-SAME:                                                   %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "string", fir.fortran_attrs = #fir.var_attrs<intent_inout>}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
 ! CHECK:           %[[VAL_1:.*]] = arith.constant 2 : index
 ! CHECK:           %[[VAL_2:.*]] = arith.constant 3 : index
 ! CHECK:           %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope



More information about the flang-commits mailing list