llvm/clang/test/InstallAPI/cpp.test

// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json

// Invoke C++ with no-rtti.
// RUN: clang-installapi -target arm64-apple-macos13.1 \
// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ -dynamiclib \
// RUN: -install_name @rpath/lib/libcpp.dylib -fno-rtti \
// RUN: %t/inputs.json -o %t/no-rtti.tbd 2>&1 | FileCheck %s --allow-empty

// RUN: llvm-readtapi -compare %t/no-rtti.tbd \
// RUN: %t/expected-no-rtti.tbd 2>&1 | FileCheck %s --allow-empty

// Invoke C++ with rtti.
// RUN: clang-installapi -target arm64-apple-macos13.1 \
// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \
// RUN: -install_name @rpath/lib/libcpp.dylib -frtti -dynamiclib \
// RUN: %t/inputs.json -o %t/rtti.tbd 2>&1 | FileCheck %s --allow-empty
// RUN: llvm-readtapi -compare %t/rtti.tbd \
// RUN: %t/expected-rtti.tbd 2>&1 | FileCheck %s --allow-empty

// CHECK-NOT: error: 
// CHECK-NOT: warning: 

//--- usr/include/basic.h
#ifndef CPP_H
#define CPP_H

inline int foo(int x) { return x + 1; }

extern int bar(int x) { return x + 1; }

inline int baz(int x) {
  static const int a[] = {1, 2, 3};
  return a[x];
}

extern "C" {
  int cFunc(const char*);
}

class Bar {
public:
  static const int x = 0;
  static int y;

  inline int func1(int x) { return x + 2; }
  inline int func2(int x);
  int func3(int x);
};

class __attribute__((visibility("hidden"))) BarI {
  static const int x = 0;
  static int y;

  inline int func1(int x) { return x + 2; }
  inline int func2(int x);
  int func3(int x);
};

int Bar::func2(int x) { return x + 3; }
inline int Bar::func3(int x) { return x + 4; }

int BarI::func2(int x) { return x + 3; }
inline int BarI::func3(int x) { return x + 4; }
#endif

//--- usr/local/include/vtable.h
// Simple test class with no virtual functions. There should be no vtable or
// RTTI.
namespace test1 {
class Simple {
public:
  void run();
};
} // end namespace test1

// Simple test class with virtual function. There should be an external vtable
// and RTTI.
namespace test2 {
class Simple {
public:
  virtual void run();
};
} // end namespace test2

// Abstract class with no sub classes. There should be no vtable or RTTI.
namespace test3 {
class Abstract {
public:
  virtual ~Abstract() {}
  virtual void run() = 0;
};
} // end namespace test3

// Abstract base class with a sub class. There should be weak-def RTTI for the
// abstract base class.
// The sub-class should have vtable and RTTI.
namespace test4 {
class Base {
public:
  virtual ~Base() {}
  virtual void run() = 0;
};

class Sub : public Base {
public:
  void run() override;
};
} // end namespace test4

// Abstract base class with a sub class. Same as above, but with a user defined
// inlined destructor.
namespace test5 {
class Base {
public:
  virtual ~Base() {}
  virtual void run() = 0;
};

class Sub : public Base {
public:
  virtual ~Sub() {}
  void run() override;
};
} // end namespace test5

// Abstract base class with a sub class. Same as above, but with a different
// inlined key method.
namespace test6 {
class Base {
public:
  virtual ~Base() {}
  virtual void run() = 0;
};

class Sub : public Base {
public:
  virtual void foo() {}
  void run() override;
};
} // end namespace test6

// Abstract base class with a sub class. Overloaded method is implemented
// inline. No vtable or RTTI.
namespace test7 {
class Base {
public:
  virtual ~Base() {}
  virtual bool run() = 0;
};

class Sub : public Base {
public:
  bool run() override { return true; }
};
} // end namespace test7

// Abstract base class with a sub class. Overloaded method has no inline
// attribute and is recognized as key method,
// but is later implemented inline. Weak-def RTTI only.
namespace test8 {
class Base {
public:
  virtual ~Base() {}
  virtual void run() = 0;
};

class Sub : public Base {
public:
  void run() override;
};

inline void Sub::run() {}
} // end namespace test8

namespace test9 {
class Base {
public:
  virtual ~Base() {}
  virtual void run1() = 0;
  virtual void run2() = 0;
};

class Sub : public Base {
public:
  void run1() override {}
  void run2() override;
};

inline void Sub::run2() {}
} // end namespace test9

namespace test10 {
class Base {
public:
  virtual ~Base() {}
  virtual void run1() = 0;
  virtual void run2() = 0;
};

class Sub : public Base {
public:
  void run1() override {}
  inline void run2() override;
};

void Sub::run2() {}
} // end namespace test10

namespace test11 {
class Base {
public:
  virtual ~Base() {}
  virtual void run1() = 0;
  virtual void run2() = 0;
  virtual void run3() = 0;
};

class Sub : public Base {
public:
  void run1() override {}
  void run2() override;
  void run3() override;
};

inline void Sub::run2() {}
} // end namespace test11

namespace test12 {
template <class T> class Simple {
public:
  virtual void foo() {}
};
extern template class Simple<int>;
} // end namespace test12

namespace test13 {
class Base {
public:
  virtual ~Base() {}
  virtual void run1() = 0;
  virtual void run2() {};
  virtual void run3(); // key function.
};

class Sub : public Base {
public:
  void run1() override {}
  void run2() override {}
};

} // end namespace test13

namespace test14 {

class __attribute__((visibility("hidden"))) Base
{
public:
    Base() {}
    virtual ~Base(); // keyfunction.
    virtual void run1() const = 0;
};

class Sub : public Base
{
public:
    Sub();
    virtual ~Sub();
    virtual void run1() const;
    void run2() const {}
};

} // end namespace test14

namespace test15 {

class Base {
public:
  virtual ~Base() {}
  virtual void run() {};
};

class Base1 {
public:
  virtual ~Base1() {}
  virtual void run1() {};
};

class Sub : public Base, public Base1 {
public:
  Sub() {}
  ~Sub();
  void run() override;
  void run1() override;
};

class Sub1 : public Base, public Base1 {
public:
  Sub1() {}
  ~Sub1() = default;
  void run() override;
  void run1() override;
};

} // end namespace test15

//--- usr/local/include/templates.h
#ifndef TEMPLATES_H
#define TEMPLATES_H

namespace templates {

// Full specialization.
template <class T> int foo1(T a) { return 1; }
template <> int foo1<int>(int a);
extern template int foo1<short>(short a);

template <class T> int foo2(T a);

// Partial specialization.
template <class A, class B> class Partial {
  static int run(A a, B b) { return a + b; }
};

template <class A> class Partial<A, int> {
  static int run(A a, int b) { return a - b; }
};

template <class T> class Foo {
public:
  Foo();
  ~Foo();
};

template <class T> class Bar {
public:
  Bar();
  ~Bar() {}

  inline int bazinga() { return 7; }
};

extern template class Bar<int>;

class Bazz {
public:
  Bazz() {}

  template <class T> int buzz(T a);

  float implicit() const { return foo1(0.0f); }
};

template <class T> int Bazz::buzz(T a) { return sizeof(T); }

template <class T> struct S { static int x; };

template <class T> int S<T>::x = 0;

} // end namespace templates.

#endif


//--- inputs.json.in
{
  "headers": [ {
    "path" : "DSTROOT/usr/include/basic.h",
    "type" : "public"
  }, 
  {
    "path" : "DSTROOT/usr/local/include/vtable.h",
    "type" : "private"
  },
  {
    "path" : "DSTROOT/usr/local/include/templates.h",
    "type" : "private"
  }
  ],
  "version": "3"
}

//--- expected-no-rtti.tbd
{
  "main_library": {
    "compatibility_versions": [
      {
        "version": "0"
      }
    ],
    "current_versions": [
      {
        "version": "0"
      }
    ],
    "exported_symbols": [
      {
        "data": {
          "global": [
            "__ZTVN6test143SubE", "__ZTVN6test113SubE", "__ZTVN5test26SimpleE",
            "__ZTVN5test53SubE", "__ZTVN6test154Sub1E", "__ZTVN6test153SubE",
            "__ZN3Bar1yE", "__ZTVN5test43SubE", "__ZTVN5test63SubE",
            "__ZTVN6test134BaseE"
          ],
          "weak": [
            "__ZTVN6test126SimpleIiEE"
          ]
        },
        "text": {
          "global": [
            "__ZN6test153Sub3runEv", "__ZN6test154Sub13runEv",
            "__Z3bari", "__ZThn8_N6test153SubD1Ev",
            "__ZNK6test143Sub4run1Ev", "__ZN6test154Sub14run1Ev",
            "__ZThn8_N6test153Sub4run1Ev", "__ZN6test143SubD1Ev",
            "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv",
            "__ZN5test43Sub3runEv", "__ZN6test113Sub4run3Ev", "__ZN6test153SubD2Ev",
            "__ZN5test53Sub3runEv", "__ZN6test153SubD1Ev", "__ZN6test143SubC1Ev",
            "__ZN9templates4foo1IiEEiT_", "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv",
            "__ZN5test26Simple3runEv", "__ZN6test153SubD0Ev",
            "__ZN6test143SubD2Ev", "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev",
            "__ZThn8_N6test153SubD0Ev", "__ZThn8_N6test154Sub14run1Ev", "_cFunc"
          ],
          "weak": [
            "__ZN9templates3BarIiED2Ev", "__ZN9templates3BarIiEC2Ev",
            "__ZN9templates3BarIiEC1Ev", "__ZN9templates3BarIiED1Ev",
            "__ZN6test126SimpleIiE3fooEv", "__ZN9templates3BarIiE7bazingaEv",
            "__ZN9templates4foo1IsEEiT_"
          ]
        }
      }
    ],
    "flags": [
      {
        "attributes": [
          "not_app_extension_safe"
        ]
      }
    ],
    "install_names": [
      {
        "name": "@rpath/lib/libcpp.dylib"
      }
    ],
    "target_info": [
      {
        "min_deployment": "13.1",
        "target": "arm64-macos"
      }
    ]
  },
  "tapi_tbd_version": 5
}

//--- expected-rtti.tbd
{
  "main_library": {
    "compatibility_versions": [
      {
        "version": "0"
      }
    ],
    "current_versions": [
      {
        "version": "0"
      }
    ],
    "exported_symbols": [
      {
        "data": {
          "global": [
            "__ZTVN6test143SubE", "__ZTIN5test63SubE", "__ZTSN5test26SimpleE",
            "__ZTIN6test153SubE", "__ZTVN6test113SubE", "__ZTIN5test43SubE",
            "__ZTIN6test134BaseE", "__ZTVN5test26SimpleE", "__ZTIN5test26SimpleE",
            "__ZTSN6test134BaseE", "__ZTVN6test154Sub1E", "__ZTVN5test43SubE",
            "__ZTVN5test63SubE", "__ZTSN5test43SubE", "__ZTSN6test113SubE",
            "__ZTIN6test154Sub1E", "__ZTSN6test153SubE", "__ZTSN5test63SubE",
            "__ZTSN6test154Sub1E", "__ZTIN6test113SubE", "__ZTSN6test143SubE",
            "__ZTVN5test53SubE", "__ZTIN6test143SubE", "__ZTVN6test153SubE",
            "__ZTIN5test53SubE", "__ZN3Bar1yE", "__ZTVN6test134BaseE",
            "__ZTSN5test53SubE"
          ],
          "weak": [
            "__ZTVN6test126SimpleIiEE"
          ]
        },
        "text": {
          "global": [
            "__ZN6test154Sub13runEv", "__ZN6test153Sub3runEv", "__ZNK6test143Sub4run1Ev",
            "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", "__ZN6test153SubD2Ev",
            "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", "__ZN6test153SubD0Ev", 
            "__ZN6test143SubD2Ev", "__ZThn8_N6test154Sub14run1Ev",
            "__ZThn8_N6test153SubD0Ev", "__Z3bari", "__ZThn8_N6test153SubD1Ev",
            "__ZN6test154Sub14run1Ev", "__ZThn8_N6test153Sub4run1Ev",
            "__ZN6test143SubD1Ev", "__ZN5test43Sub3runEv",
            "__ZN6test113Sub4run3Ev", "__ZN5test53Sub3runEv", "__ZN6test143SubC1Ev",
            "__ZN6test153SubD1Ev", "__ZN9templates4foo1IiEEiT_", "__ZN5test26Simple3runEv",
            "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", "_cFunc"
          ],
          "weak": [
            "__ZN9templates3BarIiEC2Ev", "__ZN9templates3BarIiEC1Ev",
            "__ZN9templates3BarIiED1Ev", "__ZN6test126SimpleIiE3fooEv",
            "__ZN9templates4foo1IsEEiT_", "__ZN9templates3BarIiED2Ev",
            "__ZN9templates3BarIiE7bazingaEv"
          ]
        }
      }
    ],
    "flags": [
      {
        "attributes": [
          "not_app_extension_safe"
        ]
      }
    ],
    "install_names": [
      {
        "name": "@rpath/lib/libcpp.dylib"
      }
    ],
    "target_info": [
      {
        "min_deployment": "13.1",
        "target": "arm64-macos"
      }
    ]
  },
  "tapi_tbd_version": 5
}