llvm/clang/test/CodeGenObjCXX/encode.mm

// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++98 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX98,CHECK-NO-TEMP-SPEC %s
// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++20 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX20,CHECK-NO-TEMP-SPEC %s
// RUN: %clang_cc1 -Wno-objc-root-class -std=gnu++20 %s -triple=x86_64-apple-darwin10 -fobjc-encode-cxx-class-template-spec -emit-llvm -o - | FileCheck --check-prefixes CHECK,CHECKCXX20,CHECK-TEMP-SPEC %s

// CHECK: v17@0:8{vector<float, float, float>=}16
// CHECK: {vector<float, float, float>=}
// CHECK: v24@0:816

template <typename T1, typename T2, typename T3> struct vector {
  vector();
  vector(T1,T2,T3);
};

typedef vector< float, float, float > vector3f;

@interface SceneNode
{
 vector3f position;
}

@property (assign, nonatomic) vector3f position;

@end

@interface MyOpenGLView
{
@public
  vector3f position;
}
@property vector3f position;
@end

@implementation MyOpenGLView

@synthesize position;

-(void)awakeFromNib {
 SceneNode *sn;
 vector3f VF3(1.0, 1.0, 1.0);
 [sn setPosition:VF3];
}
@end


class Int3 { int x, y, z; };

// Enforce @encoding for member pointers.
@interface MemPtr {}
- (void) foo: (int (Int3::*)) member;
@end
@implementation MemPtr
- (void) foo: (int (Int3::*)) member {
}
@end

typedef float HGVec4f __attribute__ ((vector_size(16)));

@interface RedBalloonHGXFormWrapper {
  HGVec4f m_Transform[4];
}
@end

@implementation RedBalloonHGXFormWrapper
@end

namespace rdar9357400 {
  template<int Dim1 = -1, int Dim2 = -1> struct fixed {
      template<int D> struct rebind { typedef fixed<D> other; };
  };
  
  template<typename Element, int Size>
  class fixed_1D
  {
  public:
      typedef Element value_type;
      typedef value_type array_impl[Size];
    protected:
      array_impl                  m_data;
  };
  
  template<typename Element, typename Alloc>
  class vector;
  
  template<typename Element, int Size>
  class vector< Element, fixed<Size> >
  : public fixed_1D<Element,Size> { };

  typedef vector< float,  fixed<4> > vector4f;

  // FIXME: This difference is due to D76801. It was probably an unintentional change. Maybe we want to undo it?
  // @encoding for C++ is dependent on the TypePrinter implementation, which is a known issue. But since there
  // are currently no system frameworks that vend Objective-C++ types, a potential ABI break caused by changes
  // to the TypePrinter should not be a concern.
  // CHECKCXX98: @_ZN11rdar93574002ggE ={{.*}} constant [45 x i8] c"{vector<float, rdar9357400::fixed<4> >=[4f]}\00"
  // CHECKCXX20: @_ZN11rdar93574002ggE ={{.*}} constant [44 x i8] c"{vector<float, rdar9357400::fixed<4>>=[4f]}\00"
  extern const char gg[] = @encode(vector4f);
}

namespace rdar9624314 {
  struct B2 { int x; };
  struct B3 {};
  struct S : B2, B3 {};

  // CHECK: @_ZN11rdar96243142ggE ={{.*}} constant [6 x i8] c"{S=i}\00"
  extern const char gg[] = @encode(S);

  struct S2 { unsigned : 0; int x; unsigned : 0; };
  // CHECK: @_ZN11rdar96243142g2E ={{.*}} constant [11 x i8] c"{S2=b0ib0}\00"
  extern const char g2[] = @encode(S2);
}

namespace test {
  class Foo {
  public:
   virtual void f() {};
  };
  
  class Bar {
  public:
   virtual void g() {};
  };
  
  class Zoo : virtual public Foo, virtual public Bar {
  public:
   int x;
   int y;
  };

  // CHECK: @_ZN4test3ecdE ={{.*}} constant [15 x i8] c"{Zoo=^^?ii^^?}\00"
  extern const char ecd[] = @encode(Zoo);
}

struct Base1 {
  char x;
};

struct DBase : public Base1 {
  double x;
  virtual ~DBase();
};

struct Sub_with_virt : virtual DBase {
  long x;
};

struct Sub2 : public Sub_with_virt, public Base1, virtual DBase {
  float x;
};

// CHECK: @g1 ={{.*}} constant [10 x i8] c"{Base1=c}\00"
extern const char g1[] = @encode(Base1);

// CHECK: @g2 ={{.*}} constant [14 x i8] c"{DBase=^^?cd}\00"
extern const char g2[] = @encode(DBase);

// CHECK: @g3 ={{.*}} constant [26 x i8] c"{Sub_with_virt=^^?q^^?cd}\00"
extern const char g3[] = @encode(Sub_with_virt);

// CHECK: @g4 ={{.*}} constant [19 x i8] c"{Sub2=^^?qcf^^?cd}\00"
extern const char g4[] = @encode(Sub2);

// http://llvm.org/PR9927
class allocator {
};
class basic_string     {
struct _Alloc_hider : allocator       {
char* _M_p;
};
_Alloc_hider _M_dataplus;
};

// CHECK: @g5 ={{.*}} constant [32 x i8] c"{basic_string={_Alloc_hider=*}}\00"
extern const char g5[] = @encode(basic_string);


// PR10990
struct CefBase {
  virtual ~CefBase() {}
};
struct CefBrowser : public virtual CefBase {};
struct CefBrowserImpl : public CefBrowser {};
// CHECK: @g6 ={{.*}} constant [21 x i8] c"{CefBrowserImpl=^^?}\00"
extern const char g6[] = @encode(CefBrowserImpl);

// PR10990_2
struct CefBase2 {
  virtual ~CefBase2() {}
  int i;
};
struct CefBrowser2 : public virtual CefBase2 {};
struct CefBrowserImpl2 : public CefBrowser2 {};
// CHECK: @g7 ={{.*}} constant [26 x i8] c"{CefBrowserImpl2=^^?^^?i}\00"
extern const char g7[] = @encode(CefBrowserImpl2);

struct Empty {};

struct X : Empty { 
  int array[10];
};

struct Y : Empty {
  X vec;
};

// CHECK: @g8 ={{.*}} constant [14 x i8] c"{Y={X=[10i]}}\00"
extern const char g8[] = @encode(Y);


class dynamic_class {
public:
  virtual ~dynamic_class();
};
@interface has_dynamic_class_ivar
@end
@implementation has_dynamic_class_ivar {
  dynamic_class dynamic_class_ivar;
}
@end
// CHECK: private unnamed_addr constant [41 x i8] c"{dynamic_class=\22_vptr$dynamic_class\22^^?}\00"

namespace PR17142 {
  struct A { virtual ~A(); };
  struct B : virtual A { int y; };
  struct C { virtual ~C(); int z; };
  struct D : C, B { int a; };
  struct E : D {};
  // CHECK: @_ZN7PR171421xE ={{.*}} constant [14 x i8] c"{E=^^?i^^?ii}\00"
  extern const char x[] = @encode(E);
}

// This test used to cause infinite recursion.
template<typename T>
struct S {
  typedef T Ty;
  Ty *t;
};

@interface N
{
  S<N> a;
}
@end

@implementation N
@end

const char *expand_struct() {
  // CHECK: @{{.*}} = private unnamed_addr constant [13 x i8] c"{N={S<N>=@}}\00"
  return @encode(N);
}

#if __cplusplus >= 202002L
namespace PR48048 {
  struct F {};
  struct I {
    int m;
    [[no_unique_address]] F n;
  };
  // CHECKCXX20: @_ZN7PR480481xE ={{.*}} constant [6 x i8] c"{I=i}\00"
  extern const char x[] = @encode(I);
}
#endif

namespace test_cxx_template_specialization {
template <class T>
struct B0 {
  T a;
};
struct D0 : B0<int> {};
struct D1 : D0 {};
struct D2 : virtual B0<int> {};
struct S0 {
  B0<int> a;
};
struct S1 {
  B0<int> *a;
};
struct S2 {
  S1 *a;
};
template <class T>
union U0 {
  T a;
};
typedef B0<int> TD0;
typedef B0<int> *Array0[4];

template <class T>
struct Outer0 {
  struct Inner0 {
    int a;
  };
  template <class T1>
  struct Inner1 {
    T a;
    T1 b;
  };
};

// CHECK: @[[STR22:.*]] = {{.*}} [12 x i8] c"{B0<int>=i}\00"
// CHECK: @_ZN32test_cxx_template_specialization2b0E = global ptr @[[STR22]]
// CHECK-NO-TEMP-SPEC: @[[STR23:.*]] = {{.*}} [3 x i8] c"^v\00"
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b01E = global ptr @[[STR23]]
// CHECK-TEMP-SPEC: @[[STR23:.*]] = {{.*}} [13 x i8] c"^{B0<int>=i}\00"
// CHECK-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b01E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3b02E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d0E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d1E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2d2E = global ptr @[[STR23]]
// CHECK: @[[STR24:.*]] = {{.*}} [7 x i8] c"^^{D2}\00"
// CHECK: @_ZN32test_cxx_template_specialization3d21E = global ptr @[[STR24]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2s0E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2s1E = global ptr @[[STR23]]
// CHECK: @[[STR25:.*]] = {{.*}} [12 x i8] c"^{S2=^{S1}}\00"
// CHECK: @_ZN32test_cxx_template_specialization2s2E = global ptr @[[STR25]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2u0E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization3td0E = global ptr @[[STR23]]
// CHECK-NO-TEMP-SPEC: @[[STR26:.*]] = {{.*}} [6 x i8] c"[4^v]\00"
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization2a0E = global ptr @[[STR26]]
// CHECK: @[[STR27:.*]] = {{.*}} [11 x i8] c"^{Inner0=}\00"
// CHECK: @_ZN32test_cxx_template_specialization6inner0E = global ptr @[[STR27]]
// CHECK-NO-TEMP-SPEC: @_ZN32test_cxx_template_specialization6inner1E = global ptr @.str.23
// CHECK-TEMP-SPEC: @[[STR34:.*]] = {{.*}} [18 x i8] c"^{Inner1<float>=}\00"
// CHECK-TEMP-SPEC: @_ZN32test_cxx_template_specialization6inner1E = global ptr @[[STR34]]

const char *b0 = @encode(B0<int>);
const char *b01 = @encode(B0<int> *);
const char *b02 = @encode(B0<int> &);
const char *d0 = @encode(D0 *);
const char *d1 = @encode(D1 *);
const char *d2 = @encode(D2 *);
const char *d21 = @encode(D2 **);
const char *s0 = @encode(S0 *);
const char *s1 = @encode(S1 *);
const char *s2 = @encode(S2 *);
const char *u0 = @encode(U0<int> *);
const char *td0 = @encode(TD0 *);
const char *a0 = @encode(Array0);
const char *inner0 = @encode(Outer0<int>::Inner0 *);
const char *inner1 = @encode(Outer0<int>::Inner1<float> *);
}

#if __cplusplus >= 202002L
namespace GH71250 {
  struct Empty {};
  struct S {
    [[no_unique_address]] Empty a;
    long b;
    long c;
  };

  // CHECKCXX20: @_ZN7GH712501sE =  constant [7 x i8] c"{S=qq}\00", align 1
  extern const char s[] = @encode(S);
}
#endif