================
@@ -400,13 +400,126 @@ def VoidPtr : Type<
       "cir::VoidType::get($_builder.getContext()))"> {
 }
 
+//===----------------------------------------------------------------------===//
+// StructType
+//
+// The base type for all RecordDecls.
+//===----------------------------------------------------------------------===//
+
+def CIR_StructType : CIR_Type<"Struct", "struct",
+    [
+      DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+      MutableType,
+    ]> {
+  let summary = "CIR struct type";
+  let description = [{
+    Each unique clang::RecordDecl is mapped to a `cir.struct` and any object in
+    C/C++ that has a struct type will have a `cir.struct` in CIR.
+
+    There are three possible formats for this type:
+
+     - Identified and complete structs: unique name and a known body.
+     - Identified and incomplete structs: unique name and unknown body.
+     - Anonymous structs: no name and a known body.
+
+    Identified structs are uniqued by their name, and anonymous structs are
+    uniqued by their body. This means that two anonymous structs with the same
+    body will be the same type, and two identified structs with the same name
+    will be the same type. Attempting to build a struct with an existing name,
+    but a different body will result in an error.
+
+    A few examples:
+
+    ```mlir
+        !complete = !cir.struct<struct "complete" {!cir.int<u, 8>}>
+        !incomplete = !cir.struct<struct "incomplete" incomplete>
+        !anonymous = !cir.struct<struct {!cir.int<u, 8>}>
+    ```
+
+    Incomplete structs are mutable, meaning they can be later completed with a
+    body automatically updating in place every type in the code that uses the
+    incomplete struct. Mutability allows for recursive types to be represented,
+    meaning the struct can have members that refer to itself. This is useful 
for
+    representing recursive records and is implemented through a special syntax.
+    In the example below, the `Node` struct has a member that is a pointer to a
+    `Node` struct:
+
+    ```mlir
+        !struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct
+        "Node">>}>
+    ```
+  }];
+
+  let parameters = (ins
+    OptionalArrayRefParameter<"mlir::Type">:$members,
+    OptionalParameter<"mlir::StringAttr">:$name,
+    "bool":$incomplete,
+    "bool":$packed,
+    "bool":$padded,
+    "StructType::RecordKind":$kind
+  );
+
+  // StorageClass is defined in C++ for mutability.
+  let storageClass = "StructTypeStorage";
+  let genStorageClass = 0;
+
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+
+  let builders = [
+    // Create an identified and incomplete struct type.
+    TypeBuilder<(ins
+      "mlir::StringAttr":$name,
+      "RecordKind":$kind
+    ), [{
+      return $_get($_ctxt, /*members=*/llvm::ArrayRef<Type>{}, name,
+                         /*incomplete=*/true, /*packed=*/false,
+                         /*padded=*/false, kind);
+    }]>];
+
+  let extraClassDeclaration = [{
+    using Base::verifyInvariants;
+
+    enum RecordKind : uint32_t { Class, Union, Struct };
+
+    bool isClass() const { return getKind() == RecordKind::Class; };
+    bool isStruct() const { return getKind() == RecordKind::Struct; };
----------------
andykaylor wrote:

I'm not sure. I want to say that it has to do with understanding the intent of 
the source code, but as you say there is no reason that the user can't have 
been using them interchangeably. I just verified that if I create a `struct` 
with a virtual method and a base class (declared with `class`), the incubator 
still calls it a `struct` here..

https://github.com/llvm/llvm-project/pull/135105
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to