diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -594,8 +594,8 @@
       // OpenACC data-sharing attribute
       AccPrivate, AccFirstPrivate, AccShared,
       // OpenACC data-mapping attribute
-      AccCopy, AccCopyIn, AccCopyOut, AccCreate, AccDelete, AccPresent, AccLink,
-      AccDeviceResident, AccDevicePtr,
+      AccCopy, AccCopyIn, AccCopyInReadOnly, AccCopyOut, AccCreate, AccDelete,
+      AccPresent, AccLink, AccDeviceResident, AccDevicePtr,
       // OpenACC declare
       AccDeclare,
       // OpenACC data-movement attribute
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -877,7 +877,8 @@
     os << "!$acc declare ";
     if (symbol.test(Symbol::Flag::AccCopy)) {
       os << "copy";
-    } else if (symbol.test(Symbol::Flag::AccCopyIn)) {
+    } else if (symbol.test(Symbol::Flag::AccCopyIn) ||
+        symbol.test(Symbol::Flag::AccCopyInReadOnly)) {
       os << "copyin";
     } else if (symbol.test(Symbol::Flag::AccCopyOut)) {
       os << "copyout";
@@ -892,7 +893,11 @@
     } else if (symbol.test(Symbol::Flag::AccLink)) {
       os << "link";
     }
-    os << "(" << symbol.name() << ")\n";
+    os << "(";
+    if (symbol.test(Symbol::Flag::AccCopyInReadOnly)) {
+      os << "readonly: ";
+    }
+    os << symbol.name() << ")\n";
   }
 }
 
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -167,7 +167,14 @@
 
   bool Pre(const parser::AccClause::Copyin &x) {
     const auto &objectList{std::get<parser::AccObjectList>(x.v.t)};
-    ResolveAccObjectList(objectList, Symbol::Flag::AccCopyIn);
+    const auto &modifier{
+        std::get<std::optional<parser::AccDataModifier>>(x.v.t)};
+    if (modifier &&
+        (*modifier).v == parser::AccDataModifier::Modifier::ReadOnly) {
+      ResolveAccObjectList(objectList, Symbol::Flag::AccCopyInReadOnly);
+    } else {
+      ResolveAccObjectList(objectList, Symbol::Flag::AccCopyIn);
+    }
     return false;
   }
 
@@ -246,7 +253,8 @@
       Symbol::Flag::AccDevice, Symbol::Flag::AccHost, Symbol::Flag::AccSelf};
 
   Symbol::Flags accFlagsRequireMark{Symbol::Flag::AccCreate,
-      Symbol::Flag::AccCopyIn, Symbol::Flag::AccCopy, Symbol::Flag::AccCopyOut,
+      Symbol::Flag::AccCopyIn, Symbol::Flag::AccCopyInReadOnly,
+      Symbol::Flag::AccCopy, Symbol::Flag::AccCopyOut,
       Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
       Symbol::Flag::AccLink, Symbol::Flag::AccPresent};
 
diff --git a/flang/test/Semantics/OpenACC/acc-module.f90 b/flang/test/Semantics/OpenACC/acc-module.f90
--- a/flang/test/Semantics/OpenACC/acc-module.f90
+++ b/flang/test/Semantics/OpenACC/acc-module.f90
@@ -7,6 +7,9 @@
   real :: data_copyin(10)
   !$acc declare copyin(data_copyin)
 
+  real :: data_copyinro(10)
+  !$acc declare copyin(readonly: data_copyinro)
+
   real :: data_device_resident(20)
   !$acc declare device_resident(data_device_resident)
 
@@ -20,6 +23,8 @@
 ! !$acc declare create(data_create)
 ! real(4)::data_copyin(1_8:10_8)
 ! !$acc declare copyin(data_copyin)
+! real(4)::data_copyinro(1_8:10_8)
+! !$acc declare copyin(readonly: data_copyinro)
 ! real(4)::data_device_resident(1_8:20_8)
 ! !$acc declare device_resident(data_device_resident)
 ! integer(4)::data_link(1_8:50_8)