@@ -207,6 +207,35 @@ static bool hasExplicitLowerBounds(mlir::Value shape) {
207207 mlir::isa<fir::ShapeShiftType, fir::ShiftType>(shape.getType ());
208208}
209209
210+ static std::pair<mlir::Type, mlir::Value>
211+ updateTypeWithVolatility (mlir::Type inputType, mlir::Value memref,
212+ mlir::OpBuilder &builder,
213+ fir::FortranVariableFlagsAttr fortran_attrs) {
214+ if (mlir::isa<fir::BoxType, fir::ReferenceType>(inputType) && fortran_attrs &&
215+ bitEnumContainsAny (fortran_attrs.getFlags (),
216+ fir::FortranVariableFlagsEnum::fortran_volatile)) {
217+ const bool isPointer = bitEnumContainsAny (
218+ fortran_attrs.getFlags (), fir::FortranVariableFlagsEnum::pointer);
219+ auto updateType = [&](auto t) {
220+ using FIRT = decltype (t);
221+ // If an entity is a pointer, the entity it points to is volatile, as far
222+ // as consumers of the pointer are concerned.
223+ auto elementType = t.getEleTy ();
224+ const bool elementTypeIsVolatile =
225+ isPointer || fir::isa_volatile_type (elementType);
226+ auto newEleTy =
227+ fir::updateTypeWithVolatility (elementType, elementTypeIsVolatile);
228+ inputType = FIRT::get (newEleTy, true );
229+ };
230+ llvm::TypeSwitch<mlir::Type>(inputType)
231+ .Case <fir::ReferenceType, fir::BoxType>(updateType)
232+ .Default ([](mlir::Type t) { return t; });
233+ memref =
234+ builder.create <fir::VolatileCastOp>(memref.getLoc (), inputType, memref);
235+ }
236+ return std::make_pair (inputType, memref);
237+ }
238+
210239void hlfir::DeclareOp::build (mlir::OpBuilder &builder,
211240 mlir::OperationState &result, mlir::Value memref,
212241 llvm::StringRef uniq_name, mlir::Value shape,
@@ -217,22 +246,8 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
217246 auto nameAttr = builder.getStringAttr (uniq_name);
218247 mlir::Type inputType = memref.getType ();
219248 bool hasExplicitLbs = hasExplicitLowerBounds (shape);
220- if (auto refType = mlir::dyn_cast<fir::ReferenceType>(inputType);
221- fortran_attrs && refType &&
222- bitEnumContainsAny (fortran_attrs.getFlags (),
223- fir::FortranVariableFlagsEnum::fortran_volatile)) {
224- auto eleType = refType.getEleTy ();
225- const bool isPointer = bitEnumContainsAny (
226- fortran_attrs.getFlags (), fir::FortranVariableFlagsEnum::pointer);
227- if (isPointer) {
228- // If an entity is a pointer, the entity it points to is volatile, as far
229- // as consumers of the pointer are concerned.
230- eleType = fir::updateTypeWithVolatility (eleType, true );
231- }
232- inputType = fir::ReferenceType::get (eleType, /* isVolatile=*/ true );
233- memref =
234- builder.create <fir::VolatileCastOp>(memref.getLoc (), inputType, memref);
235- }
249+ std::tie (inputType, memref) =
250+ updateTypeWithVolatility (inputType, memref, builder, fortran_attrs);
236251 mlir::Type hlfirVariableType =
237252 getHLFIRVariableType (inputType, hasExplicitLbs);
238253 build (builder, result, {hlfirVariableType, inputType}, memref, shape,
0 commit comments