diff --git a/flang/docs/PolymorphicEntities.md b/flang/docs/PolymorphicEntities.md --- a/flang/docs/PolymorphicEntities.md +++ b/flang/docs/PolymorphicEntities.md @@ -83,7 +83,8 @@ ### Unlimited polymorphic entities `CLASS(*)` -The unlimited polymorphic entity is represented as a class type with `*`. +The unlimited polymorphic entity is represented as a class type with `none` as +element type. **Fortran** ```fortran @@ -95,7 +96,7 @@ **FIR** ```c -func.func @bar(%x : !fir.class<*>) +func.func @bar(%x : !fir.class) ``` ### Assumed-type `TYPE(*)` diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -304,7 +304,7 @@ fir::KindTy kind); inline bool BaseBoxType::classof(mlir::Type type) { - return type.isa(); + return type.isa(); } } // namespace fir diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -138,6 +138,26 @@ }]; } +def fir_ClassType : FIR_Type<"Class", "class", [], "BaseBoxType"> { + let summary = "Class type"; + + let description = [{ + Class type is used to model the Fortran CLASS instrinsic type. A class type + is equivalent to a fir.box type with a dynamic type. + }]; + + let parameters = (ins "mlir::Type":$eleTy); + + let builders = [ + TypeBuilderWithInferredContext<(ins "mlir::Type":$eleTy), [{ + return $_get(eleTy.getContext(), eleTy); + }]> + ]; + + let genVerifyDecl = 1; + let assemblyFormat = "`<` $eleTy `>`"; +} + def fir_ComplexType : FIR_Type<"Complex", "complex"> { let summary = "Complex type"; diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -440,6 +440,19 @@ printer << '>'; } +//===----------------------------------------------------------------------===// +// ClassType +//===----------------------------------------------------------------------===// + +mlir::LogicalResult +fir::ClassType::verify(llvm::function_ref emitError, + mlir::Type eleTy) { + if (eleTy.isa()) + return mlir::success(); + return emitError() << "invalid element type\n"; +} + //===----------------------------------------------------------------------===// // ComplexType //===----------------------------------------------------------------------===// @@ -930,7 +943,8 @@ mlir::Type BaseBoxType::getEleTy() const { return llvm::TypeSwitch(*this) - .Case([](auto type) { return type.getEleTy(); }); + .Case( + [](auto type) { return type.getEleTy(); }); } //===----------------------------------------------------------------------===// @@ -938,11 +952,11 @@ //===----------------------------------------------------------------------===// void FIROpsDialect::registerTypes() { - addTypes(); + addTypes(); fir::ReferenceType::attachInterface>( *getContext()); diff --git a/flang/test/Fir/fir-types.fir b/flang/test/Fir/fir-types.fir --- a/flang/test/Fir/fir-types.fir +++ b/flang/test/Fir/fir-types.fir @@ -1,6 +1,6 @@ // Test the FIR types // Parse types and check that we can reparse what we print. -// RUN: fir-opt %s | fir-opt | FileCheck %s +// RUN: fir-opt --split-input-file %s | fir-opt --split-input-file | FileCheck %s // Fortran Intrinsic types // CHECK-LABEL: func private @it1() -> !fir.int<4> @@ -18,6 +18,8 @@ func.func private @it6() -> !fir.char<2,10> func.func private @it7() -> !fir.char<4,?> +// ----- + // Fortran Derived types (records) // CHECK-LABEL: func private @dvd1() -> !fir.type // CHECK-LABEL: func private @dvd2() -> !fir.type @@ -34,6 +36,8 @@ func.func private @dvd6() -> !fir.type>}> func.func private @dvd7() -> !fir.type +// ----- + // FIR array types // CHECK-LABEL: func private @arr1() -> !fir.array<10xf32> // CHECK-LABEL: func private @arr2() -> !fir.array<10x10xf32> @@ -50,6 +54,8 @@ func.func private @arr6() -> !fir.array<*:f32> func.func private @arr7() -> !fir.array<1x2x?x4x5x6x7x8x9xf32> +// ----- + // FIR pointer-like types // CHECK-LABEL: func private @mem1() -> !fir.ref // CHECK-LABEL: func private @mem2() -> !fir.ptr @@ -64,6 +70,8 @@ func.func private @mem5() -> !fir.llvm_ptr> func.func private @mem6() -> !fir.llvm_ptr +// ----- + // FIR box types (descriptors) // CHECK-LABEL: func private @box1() -> !fir.box> // CHECK-LABEL: func private @box2() -> !fir.boxchar<2> @@ -76,6 +84,8 @@ func.func private @box4() -> !fir.box func.func private @box5() -> !fir.box> +// ----- + // FIR misc. types // CHECK-LABEL: func private @oth1() -> !fir.shape<1> // CHECK-LABEL: func private @oth2() -> !fir.field @@ -88,6 +98,28 @@ func.func private @oth4() -> !fir.shapeshift<15> func.func private @oth5() -> !fir.slice<8> +// ----- + // FIR vector // CHECK-LABEL: func private @vecty(i1) -> !fir.vector<10:i32> func.func private @vecty(i1) -> !fir.vector<10:i32> + +// ----- + +// FIR Class type +// CHECK-LABEL: class1() -> !fir.class> +// CHECK-LABEL: class2() -> !fir.class>> +// CHECK-LABEL: class3() -> !fir.class>> +// CHECK-LABEL: class4() -> !fir.class>> +// CHECK-LABEL: class5() -> !fir.class +// CHECK-LABEL: class6() -> !fir.class> +// CHECK-LABEL: class7() -> !fir.class> +// CHECK-LABEL: class8() -> !fir.class> +func.func private @class1() -> !fir.class> +func.func private @class2() -> !fir.class>> +func.func private @class3() -> !fir.class>> +func.func private @class4() -> !fir.class>> +func.func private @class5() -> !fir.class +func.func private @class6() -> !fir.class> +func.func private @class7() -> !fir.class> +func.func private @class8() -> !fir.class> diff --git a/flang/test/Fir/invalid-types.fir b/flang/test/Fir/invalid-types.fir --- a/flang/test/Fir/invalid-types.fir +++ b/flang/test/Fir/invalid-types.fir @@ -162,3 +162,8 @@ // expected-error@+1 {{expected non-function type}} func.func private @oth3() -> !fir.vector<10:> + +// ----- + +// expected-error@+1 {{invalid element type}} +func.func private @upe() -> !fir.class>