// RUN: llvm-tblgen %s | FileCheck %s // XFAIL: vg_leak // CHECK: --- Defs --- // CHECK: def A0 { // CHECK: dag a = (ops A0); // CHECK: } // CHECK: def B0 { // CHECK: dag a = (ops); // CHECK: A b = B0; // CHECK: } // CHECK: def C0 { // CHECK: dag q = (ops C0); // CHECK: } // CHECK: def D0 { // CHECK: D d = D0; // CHECK: } // CHECK: def E0 { // CHECK: E e = E0; // CHECK: } // CHECK: def F0 { // CHECK: Fa as_a = F0; // CHECK: Fb as_b = F0; // CHECK: } // CHECK: def F0x { // CHECK: Fc as_c = F0; // CHECK: } def ops; class A<dag d> { dag a = d; } // This type of self-reference is used in various places defining register // classes. def A0 : A<(ops A0)>; class B<string self> { A b = !cast<A>(self); } // A stronger form of this type of self-reference is used at least in the // SystemZ backend to define a record which is a ComplexPattern and an Operand // at the same time. def B0 : A<(ops)>, B<"B0">; // Casting C0 to C by name here is tricky, because it happens while (or rather: // before) adding C as a superclass. However, SystemZ uses this pattern. class C<string self> { dag q = (ops !cast<C>(self)); } def C0 : C<"C0">; // Explore some unused corner cases. // // A self-reference within a class may seem icky, but it unavoidably falls out // orthogonally of having forward class declarations and late resolve of self // references. class D<string self> { D d = !cast<D>(self); } def D0 : D<"D0">; class E<E x> { E e = x; } // Putting the !cast directly in the def should work as well: we shouldn't // depend on implementation details of when exactly the record is looked up. // // Note the difference between !cast<E>("E0") and plain E0: the latter wouldn't // work here because E0 does not yet have E as a superclass while the template // arguments are being parsed. def E0 : E<!cast<E>("E0")>; // Ensure that records end up with the correct type even when direct self- // references are involved. class Fa; class Fb<Fa x> { Fa as_a = x; } class Fc<Fb x> { Fb as_b = x; } def F0 : Fa, Fb<F0>, Fc<F0>; def F0x { Fc as_c = F0; }